SpaceMan astrobasewiki https://astrobase.miraheze.org/wiki/Main_Page MediaWiki 1.40.1 first-letter Media Special Talk User User talk SpaceMan SpaceMan talk File File talk MediaWiki MediaWiki talk Template Template talk Help Help talk Category Category talk UserWiki UserWiki talk User profile User profile talk Video Video talk GeoJson GeoJson talk Campaign Campaign talk TimedText TimedText talk Module Module talk Topic Navigation Navigation talk Module:Namespace detect 828 61 137 2014-04-05T17:01:23Z Canopus >Mr. Stradivarius 0 use demopage instead of page as the main "page" parameter Scribunto text/plain --[[ -------------------------------------------------------------------------------- -- -- -- NAMESPACE DETECT -- -- -- -- This module implements the {{namespace detect}} template in Lua, with a -- -- few improvements: all namespaces and all namespace aliases are supported, -- -- and namespace names are detected automatically for the local wiki. The -- -- module can also use the corresponding subject namespace value if it is -- -- used on a talk page. Parameter names can be configured for different wikis -- -- by altering the values in the "cfg" table in -- -- Module:Namespace detect/config. -- -- -- -------------------------------------------------------------------------------- --]] local data = mw.loadData('Module:Namespace detect/data') local argKeys = data.argKeys local cfg = data.cfg local mappings = data.mappings local yesno = require('Module:Yesno') local mArguments -- Lazily initialise Module:Arguments local mTableTools -- Lazily initilalise Module:TableTools local ustringLower = mw.ustring.lower local p = {} local function fetchValue(t1, t2) -- Fetches a value from the table t1 for the first key in array t2 where -- a non-nil value of t1 exists. for i, key in ipairs(t2) do local value = t1[key] if value ~= nil then return value end end return nil end local function equalsArrayValue(t, value) -- Returns true if value equals a value in the array t. Otherwise -- returns false. for i, arrayValue in ipairs(t) do if value == arrayValue then return true end end return false end function p.getPageObject(page) -- Get the page object, passing the function through pcall in case of -- errors, e.g. being over the expensive function count limit. if page then local success, pageObject = pcall(mw.title.new, page) if success then return pageObject else return nil end else return mw.title.getCurrentTitle() end end -- Provided for backward compatibility with other modules function p.getParamMappings() return mappings end local function getNamespace(args) -- This function gets the namespace name from the page object. local page = fetchValue(args, argKeys.demopage) if page == '' then page = nil end local demospace = fetchValue(args, argKeys.demospace) if demospace == '' then demospace = nil end local subjectns = fetchValue(args, argKeys.subjectns) local ret if demospace then -- Handle "demospace = main" properly. if equalsArrayValue(argKeys.main, ustringLower(demospace)) then ret = mw.site.namespaces[0].name else ret = demospace end else local pageObject = p.getPageObject(page) if pageObject then if pageObject.isTalkPage then -- Get the subject namespace if the option is set, -- otherwise use "talk". if yesno(subjectns) then ret = mw.site.namespaces[pageObject.namespace].subject.name else ret = 'talk' end else ret = pageObject.nsText end else return nil -- return nil if the page object doesn't exist. end end ret = ret:gsub('_', ' ') return ustringLower(ret) end function p._main(args) -- Check the parameters stored in the mappings table for any matches. local namespace = getNamespace(args) or 'other' -- "other" avoids nil table keys local params = mappings[namespace] or {} local ret = fetchValue(args, params) --[[ -- If there were no matches, return parameters for other namespaces. -- This happens if there was no text specified for the namespace that -- was detected or if the demospace parameter is not a valid -- namespace. Note that the parameter for the detected namespace must be -- completely absent for this to happen, not merely blank. --]] if ret == nil then ret = fetchValue(args, argKeys.other) end return ret end function p.main(frame) mArguments = require('Module:Arguments') local args = mArguments.getArgs(frame, {removeBlanks = false}) local ret = p._main(args) return ret or '' end function p.table(frame) --[[ -- Create a wikitable of all subject namespace parameters, for -- documentation purposes. The talk parameter is optional, in case it -- needs to be excluded in the documentation. --]] -- Load modules and initialise variables. mTableTools = require('Module:TableTools') local namespaces = mw.site.namespaces local cfg = data.cfg local useTalk = type(frame) == 'table' and type(frame.args) == 'table' and yesno(frame.args.talk) -- Whether to use the talk parameter. -- Get the header names. local function checkValue(value, default) if type(value) == 'string' then return value else return default end end local nsHeader = checkValue(cfg.wikitableNamespaceHeader, 'Namespace') local aliasesHeader = checkValue(cfg.wikitableAliasesHeader, 'Aliases') -- Put the namespaces in order. local mappingsOrdered = {} for nsname, params in pairs(mappings) do if useTalk or nsname ~= 'talk' then local nsid = namespaces[nsname].id -- Add 1, as the array must start with 1; nsid 0 would be lost otherwise. nsid = nsid + 1 mappingsOrdered[nsid] = params end end mappingsOrdered = mTableTools.compressSparseArray(mappingsOrdered) -- Build the table. local ret = '{| class="wikitable"' .. '\n|-' .. '\n! ' .. nsHeader .. '\n! ' .. aliasesHeader for i, params in ipairs(mappingsOrdered) do for j, param in ipairs(params) do if j == 1 then ret = ret .. '\n|-' .. '\n| <code>' .. param .. '</code>' .. '\n| ' elseif j == 2 then ret = ret .. '<code>' .. param .. '</code>' else ret = ret .. ', <code>' .. param .. '</code>' end end end ret = ret .. '\n|-' .. '\n|}' return ret end return p a4757000273064f151f0f22dc0e139092e5ff443 Template:Pagetype 10 58 131 2014-07-09T08:29:38Z Canopus >Callanecc 0 Changed protection level of Template:Pagetype: [[WP:High-risk templates|Highly visible template]]: With more than 5.5 million transclusions and cascade protections this should be full protected as well ([Edit=Allow only administrators] (indefinite) [Move= wikitext text/x-wiki {{<includeonly>safesubst:</includeonly>#invoke:pagetype|main}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> b8e6aa66678cd57877ea2c607372a45070f030a7 Template:Str rep 10 69 153 2015-04-14T16:35:55Z Canopus >Redrose64 0 Protected Template:Str rep: [[WP:High-risk templates|Highly visible template]]: 167176 transclusions ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite)) wikitext text/x-wiki {{#invoke:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|1}}<noinclude> {{Documentation}}</noinclude> 4706daa3137857f2792cc7109ca24b6d58c78dee Template:Comma separated entries 10 123 261 2015-05-26T18:05:33Z Canopus >Izkala 0 Switch to using [[Module:Separated entries]] wikitext text/x-wiki {{<includeonly>safesubst:</includeonly>#invoke:Separated entries|comma}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> f9811ed089bab742e4aad8b8463eddcc7607f062 Module:IPAc-en/data 828 82 179 2015-06-19T11:38:13Z Canopus >Mr. Stradivarius 0 switch to main data modules Scribunto text/plain -- This module processes data for [[Module:IPAc-en]]. It is intended to be -- loaded with mw.loadData. local PRONUNCIATION_MODULE = 'Module:IPAc-en/pronunciation' local PHONEME_MODULE = 'Module:IPAc-en/phonemes' local function makeData(oldData) local newData = {} for i, old in ipairs(oldData) do local new = {} for k, v in pairs(old) do if k ~= 'aliases' and k ~= 'code' then new[k] = v end end newData[old.code] = new if old.aliases then for i, alias in ipairs(old.aliases) do newData[alias] = new end end end return newData end local function main() local pronunciation = makeData(require(PRONUNCIATION_MODULE)) local phonemes = makeData(require(PHONEME_MODULE)) -- Check that no pronunciation keys are also contained in the phonemes -- data. This would cause silent, hard-to-debug errors if it went -- unchecked, so make it cause a big red error message instead. for id in pairs(pronunciation) do if phonemes[id] then error(string.format( "duplicate ID '%s' found in %s and %s", id, PRONUNCIATION_MODULE, PHONEME_MODULE )) end end return { pronunciation = pronunciation, phonemes = phonemes, } end return main() 3428d5574793b97b1b5ba91ff0c32e0418c27642 Template:OED 10 133 281 2015-07-26T16:56:33Z Canopus >PBS 0 PBS moved page [[Template:OED]] to [[Template:Cite OED]] over redirect: consistency with other similar templates such as [[template:cite ODNB]] wikitext text/x-wiki #REDIRECT [[Template:Cite OED]] {{R from move}} d5391a8c7307b290008c46b310b929153eb9440f Template:Cite journal 10 49 113 2015-11-13T02:17:24Z Canopus >Fuhghettaboutit 0 Changed protection level of Template:Cite journal: when I changed this to add template editors, I didn't realize it had cascding protection—so all my change did was make it appear as if it could be edited by them ([Edit=Allow only administrators] (in... wikitext text/x-wiki <includeonly>{{#invoke:Citation/CS1|citation |CitationClass=journal }}</includeonly><noinclude> {{documentation}} </noinclude> 50b33a0bde8c0dc83f3753f7873bcb448b565944 Template:Cite encyclopedia 10 97 209 2015-11-13T02:17:24Z Canopus >Fuhghettaboutit 0 Changed protection level of Template:Cite encyclopedia: when I changed this to add template editors, I didn't realize it had cascding protection—so all my change did was make it appear as if it could be edited by them ([Edit=Allow only administrators... wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=encyclopaedia }}</includeonly><noinclude> {{documentation}} [[Category:Lua-based templates]] </noinclude> a5fbaa0493d06b11ef4dd711383f9fd5174a4238 Template:Cite conference 10 135 285 2015-11-13T02:17:24Z Canopus >Fuhghettaboutit 0 Changed protection level of Template:Cite conference: when I changed this to add template editors, I didn't realize it had cascding protection—so all my change did was make it appear as if it could be edited by them ([Edit=Allow only administrators]... wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=conference }}</includeonly><noinclude> {{documentation}} </noinclude> 3c799319c67a4e713f07b5476ef62fa6a9efc608 Template:Nowrap 10 38 91 2015-11-28T10:13:53Z Canopus >Edokter 0 Adapt comment; edits inside noinclude blocks should not affect job queue, but won't kill parser either way. wikitext text/x-wiki <span class="nowrap">{{{1}}}</span><noinclude> {{documentation}} <!-- Categories go on the /doc page; interwikis go to Wikidata. --> </noinclude> 5d0dc6b6d89b37f4356242404f46138a4017f015 Template:Cite web 10 85 185 2016-12-05T05:36:52Z Canopus >Anthony Appleyard 0 Protected "[[Template:Cite web]]": restore old protection ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite)) wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=web }}</includeonly><noinclude> {{documentation}} </noinclude> ea1b0f38afd9728a1cf9f2e3f540887a402fab8e Template:Portal bar 10 121 257 2016-12-10T22:05:10Z Canopus >Renamed user mou89p43twvqcvm8ut9w3 0 Changed protection level for "[[Template:Portal bar]]": [[WP:High-risk templates|Highly visible template]] ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki {{#invoke:Portal bar|main}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> 147fd2e53f15534b497d1049a4ea239049ec8fbc Template:Zh 10 149 313 2017-04-27T14:29:36Z Canopus >Anthony Appleyard 0 Anthony Appleyard moved page [[Template:Zh]] to [[Template:Lang-zh]]: [[Special:Permalink/777478128|Requested]] by Jc86035 at [[WP:RM/TR]]: Consistency with other similar templates such as &#123;&#123;[[Template:Lang-fr|Lang-fr]]&#125;&#125;. wikitext text/x-wiki #REDIRECT [[Template:Lang-zh]] {{R from move}} 6aa0af2f0918a28a55a7aa2f294fc53068c3b191 Template:IPAc-en 10 80 175 2017-06-22T21:12:36Z Canopus >Nardog 0 <includeonly> wikitext text/x-wiki <includeonly>{{#invoke:IPAc-en|main}}</includeonly><noinclude> {{documentation}} </noinclude> f81b884979df2c3ec3a7275e7fb402ad585e26e4 Module:Gapnum 828 44 103 2017-10-10T17:39:00Z Canopus >MusikAnimal 0 Changed protection level for "[[Module:Gapnum]]": [[WP:High-risk templates|High-risk Lua module]]: 7,000+ transclusions ([Edit=Require extended confirmed access] (indefinite)) Scribunto text/plain local p = {} local getArgs function p.main(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end local args = getArgs(frame, {wrappers = 'Template:Gapnum'}) local n = args[1] if not n then error('Parameter 1 is required') elseif not tonumber(n) and not tonumber(n, 36) then -- Validates any number with base ≤ 36 error('Unable to convert "' .. args[1] .. '" to a number') end local gap = args.gap local precision = tonumber(args.prec) return p.gaps(n,{gap=gap,prec=precision}) end -- Not named p._main so that it has a better function name when required by Module:Val function p.gaps(n,tbl) local nstr = tostring(n) if not tbl then tbl = {} end local gap = tbl.gap or '.25em' local int_part, frac_part = p.groups(n,tbl.prec) local ret = mw.html.create('span') :css('white-space','nowrap') -- No gap necessary on first group :wikitext(table.remove(int_part,1)) -- Build int part for _, v in ipairs(int_part) do ret:tag('span') :css('margin-left',gap) :wikitext(v) end if frac_part then -- The first group after the decimal shouldn't have a gap ret:wikitext('.' .. table.remove(frac_part,1)) -- Build frac part for _, v in ipairs(frac_part) do ret:tag('span') :css('margin-left',gap) :wikitext(v) end end return ret end -- Creates tables where each element is a different group of the number function p.groups(num,precision) local nstr = tostring(num) if not precision then precision = -1 end local decimalloc = nstr:find('.', 1, true) local int_part, frac_part if decimalloc == nil then int_part = nstr else int_part = nstr:sub(1, decimalloc-1) frac_part = nstr:sub(decimalloc + 1) end -- only define ret_i as an empty table, let ret_d stay nil local ret_i,ret_d = {} -- Loop to handle most of the groupings; from right to left, so that if a group has less than 3 members, it will be the first group while int_part:len() > 3 do -- Insert in first spot, since we're moving backwards table.insert(ret_i,1,int_part:sub(-3)) int_part = int_part:sub(1,-4) end -- handle any left over numbers if int_part:len() > 0 then table.insert(ret_i,1,int_part) end if precision ~= 0 and frac_part then ret_d = {} if precision == -1 then precision = frac_part:len() end -- Reduce the length of the string if required precision is less than actual precision -- OR -- Increase it (by adding 0s) if the required precision is more than actual local offset = precision - frac_part:len() if offset < 0 then frac_part = frac_part:sub(1,precision) elseif offset > 0 then frac_part = frac_part .. string.rep('0', offset) end -- Allow groups of 3 or 2 (3 first) for v in string.gmatch(frac_part,'%d%d%d?') do table.insert(ret_d,v) end -- Preference for groups of 4 instead of groups of 1 at the end if #frac_part % 3 == 1 then if frac_part:len() == 1 then ret_d = {frac_part} else local last_g = ret_d[#ret_d] or '' last_g = last_g..frac_part:sub(-1) ret_d[#ret_d] = last_g end end end return ret_i,ret_d end return p b855346e2e3abc47591f883503c6108f922f0849 Template:Cite book 10 96 207 2017-11-15T09:11:45Z Canopus >Salix alba 0 put TD in a collapse top / bottom section wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=book }}</includeonly><noinclude> {{documentation}} {{collapse top|TemplateData}} {{Cite book/TemplateData}} {{collapse bottom}} </noinclude> c474cbe5d051e08f516083d594207d449245c717 Template:DEC 10 138 291 2018-02-23T16:29:42Z Canopus >Primefac 0 Changed protection level for "[[Template:DEC]]": [[WP:HIGHRISK|high-risk]] template with 4000+ transclusions ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki {{Str rep|{{{1}}}|-|−}}&deg;{{#ifeq: {{{2|+}}}|{{{2|-}}}|&nbsp;{{{2|}}}&prime;|}}{{#ifeq: {{{3|+}}}|{{{3|-}}}|&nbsp;{{{3|}}}&Prime;|}}<noinclude> {{documentation}} </noinclude> 6927f28c38d0a50c1b2b56e84804d862ad50264a Template:Starbox begin 10 153 321 2018-02-23T16:30:23Z Canopus >Primefac 0 Changed protection level for "[[Template:Starbox begin]]": [[WP:HIGHRISK|high-risk]] template with 4000+ transclusions ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki {| class="infobox" style="width: 22em; font-size: 88%; <!-- text-align: left; --> line-height: 1.5em" |+ style="font-size: 125%; font-weight: bold" | {{{name<includeonly>|{{PAGENAME}}</includeonly>}}}<noinclude> |}{{Documentation}}</noinclude> 115f5bb26dd6bc3e6032bfe5080e62fffdb69a80 Template:Val 10 42 99 2018-02-23T16:30:35Z Canopus >Primefac 0 Changed protection level for "[[Template:Val]]": [[WP:HIGHRISK|high-risk]] template with 4000+ transclusions ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki <includeonly>{{{{{♥|safesubst:}}}#invoke:val|main}}</includeonly><noinclude> {{documentation}} </noinclude> 4765ec60d7235aeb2b778f12eac5cdcbd4ebab5d Template:Engvar 10 142 299 2018-02-23T17:02:13Z Canopus >Primefac 0 Changed protection level for "[[Template:Engvar]]": [[WP:HIGHRISK|high-risk]] template with 2000+ transclusions ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki {{#invoke:Engvar|variants}}<noinclude> {{documentation}} </noinclude> 8a5e5d43fff0053bf6bd7fab7f761a6be4c05d21 Template:Solar luminosity 10 141 297 2018-02-23T17:02:56Z Canopus >Primefac 0 Changed protection level for "[[Template:Solar luminosity]]": [[WP:HIGHRISK|high-risk]] template with 2000+ transclusions ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki {{#if:{{{1|}}} |{{{1}}}&nbsp; }}{{#if:{{{link|}}} |[[Solar luminosity|<var>L</var><sub>&#x2609;</sub>]] |<var>L</var><sub>&#x2609;</sub> }}<noinclude> {{documentation}} </noinclude> fb6372ee064d487f11d117a91d6ae84d9980f19f Template:Solar mass 10 146 307 2018-02-23T17:02:56Z Canopus >Primefac 0 Changed protection level for "[[Template:Solar mass]]": [[WP:HIGHRISK|high-risk]] template with 2000+ transclusions ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki {{#if:{{{1|}}} |{{{1}}}&nbsp; }}{{#if:{{{link|}}} |[[Solar mass|<var>M</var><sub>&#x2609;</sub>]] |<var>M</var><sub>&#x2609;</sub> }}<noinclude> {{documentation}} </noinclude> 2a303d9d8a727c9f9ccc23508e1d17883808fbcc Template:Solar radius 10 147 309 2018-02-23T17:02:56Z Canopus >Primefac 0 Changed protection level for "[[Template:Solar radius]]": [[WP:HIGHRISK|high-risk]] template with 2000+ transclusions ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki {{#if:{{{1|}}} |{{{1}}}&nbsp; }}{{#if:{{{link|}}} |[[Solar radius|<var>R</var><sub>&#x2609;</sub>]] |<var>R</var><sub>&#x2609;</sub> }}<noinclude> {{documentation}} </noinclude> 12c29f2ba83c64dcc96a015a59244428c531f452 Template:Cite DR2 10 162 339 2018-12-07T16:26:19Z Canopus >Lithopsian 0 Lithopsian moved page [[Template:Cite DR2]] to [[Template:Cite Gaia DR2]]: As discussed wikitext text/x-wiki #REDIRECT [[Template:Cite Gaia DR2]] {{R from move}} f105cdaa4ffd5d7683d35297a855d5e4fc5c1c16 Module:Separated entries 828 74 163 2018-12-17T20:54:33Z Canopus >Amorymeltzer 0 Changed protection level for "[[Module:Separated entries]]": [[WP:High-risk templates|High-risk Lua module]]: Over 2M transclusions ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite)) Scribunto text/plain -- This module takes positional parameters as input and concatenates them with -- an optional separator. The final separator (the "conjunction") can be -- specified independently, enabling natural-language lists like -- "foo, bar, baz and qux". The starting parameter can also be specified. local compressSparseArray = require('Module:TableTools').compressSparseArray local p = {} function p._main(args) local separator = args.separator -- Decode (convert to Unicode) HTML escape sequences, such as "&#32;" for space. and mw.text.decode(args.separator) or '' local conjunction = args.conjunction and mw.text.decode(args.conjunction) or separator -- Discard values before the starting parameter. local start = tonumber(args.start) if start then for i = 1, start - 1 do args[i] = nil end end -- Discard named parameters. local values = compressSparseArray(args) return mw.text.listToText(values, separator, conjunction) end local function makeInvokeFunction(separator, conjunction, first) return function (frame) local args = require('Module:Arguments').getArgs(frame) args.separator = separator or args.separator args.conjunction = conjunction or args.conjunction args.first = first or args.first return p._main(args) end end p.main = makeInvokeFunction() p.br = makeInvokeFunction('<br />') p.comma = makeInvokeFunction(mw.message.new('comma-separator'):plain()) return p e80231ff3de01afd7f62a94e0a34dc1e67504085 Module:Engvar 828 143 301 2019-02-25T04:25:52Z Canopus >JJMC89 0 Changed protection level for "[[Module:Engvar]]": [[WP:High-risk templates|Highly visible module]]: match template ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) Scribunto text/plain -- This module implements Template:Engvar. -- Template:Engvar is to be build into the template (like an infobox), with default & variant spellings defined. -- That template should also allow parameter '|engvar=' for the editor (article page). -- The module/template Engvar then returns the spelling variant as is set in that article (for example '|engvar=en-GB'). -- The defaultWord is returned, unless the engvar input hits on a defined (en-XX) variant word. local p = {} local getArgs = require('Module:Arguments').getArgs local gsub = string.gsub local lower = string.lower local upper = string.upper function p.variants(frame) local args = getArgs(frame) return p._variants(args) end function p._variants(args) local returnWord = nil local defaultWord = args.defaultWord or '' if args.engvar == nil then -- Nothing to look for; use defaultWord right away returnWord = defaultWord elseif args.defaultLang == gsub(lower(args.engvar), '^en%-(%w%w)$', formatISO) then -- By the defaultLang, the defaultWord is asked returnWord = defaultWord else returnWord = args[gsub(lower(args.engvar), '^en%-(%w%w)$', formatISO)] end if returnWord == nil then -- No hit so far. Search by words in the engvar entered, checking the list local useLang = engvarLang(args.engvar) if useLang == nil then returnWord = defaultWord .. addMaintCat(args) else returnWord = args[useLang] or defaultWord end end return returnWord end -- Returns arguments and intermediate result. Plus the template result, in front. function p.explain(frame) local args = getArgs(frame) local ret = {} table.insert(ret, '\n\n: Settings:') table.insert(ret, 'defaultWord=' .. (args.defaultWord or '') .. '; ') table.insert(ret, 'defaultLang=' .. (args.defaultLang or '') .. '; ') table.insert(ret, 'engvarCat=' .. (args.engvarCat or '[default:yes]') .. '; ') table.insert(ret, 'engvarCatSort=' .. (args.engvarCatSort or '')) table.insert(ret, '\n\n: engvar=' .. (args.engvar or '') .. ' [input] ') local useLang = engvarLang(args.engvar or '') table.insert(ret, ' => Engvar code [used]: >' .. (useLang or '') .. '<.') for k, v in pairs(args) do if k == 'en-UK' then table.insert(ret, k .. ' ? better: use "en-GB"; ') elseif k == 'en-SA' then table.insert(ret, k .. ' ? misleading; use "en-ZA"; ') end if k == 'defaultWord' then elseif k == 'defaultLang' then elseif k == 'engvar' then elseif k == 'engvarcat' then elseif k == gsub(lower(k), '^en%-(%w%w)$', formatISO) then table.insert(ret, k .. '=' .. v .. '; ') else table.insert(ret, k .. ' [not standard:]=' .. v .. '; ') end end return (args.engvar or '') .. ' => ' .. p._variants(args) .. table.concat(ret, ' ') end -- Turn a match into pattern 'en-XX' function formatISO(country) return ('en-' .. upper(country) or '') end function engvarLang(searchEngvar) -- Search verbose language identifiers to ISO-format 'en-XX' -- Assumed: not a blank string '' to search local match = string.match searchEngvar = gsub(searchEngvar, '^%s*en%-(.*)', '%1') -- rm any opening 'en-'. searchEngvar = gsub(lower(searchEngvar), '[%s%(%)%-]', '') -- To lc, remove all: (, ) , ws, hyphen. local useLang --Special codes if match(searchEngvar, 'oxford') or searchEngvar == 'oed' then useLang = 'en-OED' -- 'oxford' to catch before anyting 'british' elseif match(searchEngvar, 'iupac') then useLang = 'en-IUPAC' -- chemistry -- Very often used elseif match(searchEngvar, 'british') or searchEngvar == 'uk' or searchEngvar == 'gbr' then useLang = 'en-GB' elseif searchEngvar == 'us' or match(searchEngvar, 'unitedstates') or searchEngvar == 'american' or searchEngvar == 'usa' then useLang = 'en-US' elseif match(searchEngvar, 'australia') or searchEngvar == 'aus' then useLang = 'en-AU' -- Often used elseif match(searchEngvar, 'india') or searchEngvar == 'ind' then useLang = 'en-IN' elseif searchEngvar == 'newzealand' or searchEngvar == 'nzl' then useLang = 'en-NZ' elseif match(searchEngvar, 'southafrica') -- not: en-SA or searchEngvar == 'zaf' then useLang = 'en-ZA' elseif searchEngvar == 'canada' or searchEngvar == 'can' then useLang = 'en-CA' elseif match(searchEngvar, 'hiberno') or match(searchEngvar, 'ireland') or match(searchEngvar, 'irish') or searchEngvar == 'irl' then useLang = 'en-EI' elseif match(searchEngvar, 'hongkong') or searchEngvar == 'hkg' then useLang = 'en-HK' -- Less often used elseif match(searchEngvar, 'jamaica') or searchEngvar == 'jam' then useLang = 'en-JM' elseif match(searchEngvar, 'malawi') or searchEngvar == 'mwi' then useLang = 'en-MW' elseif match(searchEngvar, 'nigeria') or searchEngvar == 'nga' then useLang = 'en-NG' elseif match(searchEngvar, 'pakistan') or searchEngvar == 'pak' then useLang = 'en-PK' elseif match(searchEngvar, 'philippine') or searchEngvar == 'phl' then useLang = 'en-PH' elseif match(searchEngvar, 'scotland') or match(searchEngvar, 'scottish') or searchEngvar == 'sco' then useLang = 'en-SCO' -- Has no alpha-2 code; not 'scotch' elseif match(searchEngvar, 'singapore') or searchEngvar == 'sgp' then useLang = 'en-SG' elseif match(searchEngvar, 'trinidad') or match(searchEngvar, 'tobago') or searchEngvar == 'tto' then useLang = 'en-TT' else useLang = nil end return useLang end function addMaintCat(args) local catMaintenance if args.engvarCat == 'no' then else local title = mw.title.getCurrentTitle() if title:inNamespaces(0) then -- 0=main, 10=templ, 828=module if args.engvarCatSort then catMaintenance = '|' .. args.engvarCatSort .. ', ' .. title.text end catMaintenance = '[[Category:Articles using an unknown Template:Engvar option' .. (catMaintenance or '') .. ']]' end end return catMaintenance or '' end return p c67c97cf2bc643d26781b77fd4b0d63383ab47a8 Template:Cite dictionary 10 131 277 2019-03-05T14:21:58Z Canopus >Xaosflux 0 Changed protection level for "[[Template:Cite dictionary]]": Pages alread protected from [[Wikipedia:Cascade-protected items/content]] ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite)) wikitext text/x-wiki #REDIRECT [[Template:Cite encyclopedia]] b08dc3862c41642a1bb23bc31b3764ffdce55dcc Template:Rnd 10 145 305 2019-04-20T04:09:41Z Canopus >Anthony Appleyard 0 Changed protection level for "[[Template:Rnd]]": asked ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki #REDIRECT [[Template:Round]] 60d43fe6637b72ea57395979124e0c4cea5b4f9e Template:Citation 10 124 263 2019-05-06T17:38:52Z Canopus >Trappist the monk 0 per [[Wikipedia:Templates for discussion/Log/2019 April 18#separate patent cites from Template:Citation‎|TfD]]; wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=citation }}</includeonly><noinclude> {{Documentation}} </noinclude> 682134a60c143dec260ce779777d3be2d4c94eaa Module:IPAc-en/pronunciation 828 83 181 2019-09-26T09:16:18Z Canopus >Nardog 0 add "also" etc. Scribunto text/plain -- This module contains pronunciation-key data for [[Module:IPAc-en]]. return { { code = 'lang', text = 'English:' }, { code = 'pron', text = '' }, { code = 'local', text = 'locally' }, { code = 'ipa', text = '[[International Phonetic Alphabet|IPA]]:' }, { code = 'also', text = 'also' }, { code = 'uk', text = '[[British English|UK]]:' }, { code = 'us', text = '[[American English|US]]:' }, { code = 'uklang', text = '[[British English]]:' }, { code = 'uslang', text = '[[American English]]:' }, { code = 'ukalso', text = '[[British English|UK]] also' }, { code = 'usalso', text = '[[American English|US]] also' }, { code = 'alsouk', text = 'also [[British English|UK]]:' }, { code = 'alsous', text = 'also [[American English|US]]:' }, } f4b022e065c591350dd1ee03942c104a3a096395 Template:Lang-zh 10 148 311 2019-11-06T06:28:12Z Canopus >DannyS712 0 module moved wikitext text/x-wiki <includeonly>{{#invoke:Lang-zh|Zh}}</includeonly><noinclude>{{documentation}}</noinclude> 09d0f2945fa94b8947d29d2329101bd511d11d2d Module:Arguments 828 40 95 2020-04-01T06:12:40Z Canopus >MusikAnimal 0 1 revision imported Scribunto text/plain -- This module provides easy processing of arguments passed to Scribunto from -- #invoke. It is intended for use by other Lua modules, and should not be -- called from #invoke directly. local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local arguments = {} -- Generate four different tidyVal functions, so that we don't have to check the -- options every time we call it. local function tidyValDefault(key, val) if type(val) == 'string' then val = val:match('^%s*(.-)%s*$') if val == '' then return nil else return val end else return val end end local function tidyValTrimOnly(key, val) if type(val) == 'string' then return val:match('^%s*(.-)%s*$') else return val end end local function tidyValRemoveBlanksOnly(key, val) if type(val) == 'string' then if val:find('%S') then return val else return nil end else return val end end local function tidyValNoChange(key, val) return val end local function matchesTitle(given, title) local tp = type( given ) return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title end local translate_mt = { __index = function(t, k) return k end } function arguments.getArgs(frame, options) checkType('getArgs', 1, frame, 'table', true) checkType('getArgs', 2, options, 'table', true) frame = frame or {} options = options or {} --[[ -- Set up argument translation. --]] options.translate = options.translate or {} if getmetatable(options.translate) == nil then setmetatable(options.translate, translate_mt) end if options.backtranslate == nil then options.backtranslate = {} for k,v in pairs(options.translate) do options.backtranslate[v] = k end end if options.backtranslate and getmetatable(options.backtranslate) == nil then setmetatable(options.backtranslate, { __index = function(t, k) if options.translate[k] ~= k then return nil else return k end end }) end --[[ -- Get the argument tables. If we were passed a valid frame object, get the -- frame arguments (fargs) and the parent frame arguments (pargs), depending -- on the options set and on the parent frame's availability. If we weren't -- passed a valid frame object, we are being called from another Lua module -- or from the debug console, so assume that we were passed a table of args -- directly, and assign it to a new variable (luaArgs). --]] local fargs, pargs, luaArgs if type(frame.args) == 'table' and type(frame.getParent) == 'function' then if options.wrappers then --[[ -- The wrappers option makes Module:Arguments look up arguments in -- either the frame argument table or the parent argument table, but -- not both. This means that users can use either the #invoke syntax -- or a wrapper template without the loss of performance associated -- with looking arguments up in both the frame and the parent frame. -- Module:Arguments will look up arguments in the parent frame -- if it finds the parent frame's title in options.wrapper; -- otherwise it will look up arguments in the frame object passed -- to getArgs. --]] local parent = frame:getParent() if not parent then fargs = frame.args else local title = parent:getTitle():gsub('/sandbox$', '') local found = false if matchesTitle(options.wrappers, title) then found = true elseif type(options.wrappers) == 'table' then for _,v in pairs(options.wrappers) do if matchesTitle(v, title) then found = true break end end end -- We test for false specifically here so that nil (the default) acts like true. if found or options.frameOnly == false then pargs = parent.args end if not found or options.parentOnly == false then fargs = frame.args end end else -- options.wrapper isn't set, so check the other options. if not options.parentOnly then fargs = frame.args end if not options.frameOnly then local parent = frame:getParent() pargs = parent and parent.args or nil end end if options.parentFirst then fargs, pargs = pargs, fargs end else luaArgs = frame end -- Set the order of precedence of the argument tables. If the variables are -- nil, nothing will be added to the table, which is how we avoid clashes -- between the frame/parent args and the Lua args. local argTables = {fargs} argTables[#argTables + 1] = pargs argTables[#argTables + 1] = luaArgs --[[ -- Generate the tidyVal function. If it has been specified by the user, we -- use that; if not, we choose one of four functions depending on the -- options chosen. This is so that we don't have to call the options table -- every time the function is called. --]] local tidyVal = options.valueFunc if tidyVal then if type(tidyVal) ~= 'function' then error( "bad value assigned to option 'valueFunc'" .. '(function expected, got ' .. type(tidyVal) .. ')', 2 ) end elseif options.trim ~= false then if options.removeBlanks ~= false then tidyVal = tidyValDefault else tidyVal = tidyValTrimOnly end else if options.removeBlanks ~= false then tidyVal = tidyValRemoveBlanksOnly else tidyVal = tidyValNoChange end end --[[ -- Set up the args, metaArgs and nilArgs tables. args will be the one -- accessed from functions, and metaArgs will hold the actual arguments. Nil -- arguments are memoized in nilArgs, and the metatable connects all of them -- together. --]] local args, metaArgs, nilArgs, metatable = {}, {}, {}, {} setmetatable(args, metatable) local function mergeArgs(tables) --[[ -- Accepts multiple tables as input and merges their keys and values -- into one table. If a value is already present it is not overwritten; -- tables listed earlier have precedence. We are also memoizing nil -- values, which can be overwritten if they are 's' (soft). --]] for _, t in ipairs(tables) do for key, val in pairs(t) do if metaArgs[key] == nil and nilArgs[key] ~= 'h' then local tidiedVal = tidyVal(key, val) if tidiedVal == nil then nilArgs[key] = 's' else metaArgs[key] = tidiedVal end end end end end --[[ -- Define metatable behaviour. Arguments are memoized in the metaArgs table, -- and are only fetched from the argument tables once. Fetching arguments -- from the argument tables is the most resource-intensive step in this -- module, so we try and avoid it where possible. For this reason, nil -- arguments are also memoized, in the nilArgs table. Also, we keep a record -- in the metatable of when pairs and ipairs have been called, so we do not -- run pairs and ipairs on the argument tables more than once. We also do -- not run ipairs on fargs and pargs if pairs has already been run, as all -- the arguments will already have been copied over. --]] metatable.__index = function (t, key) --[[ -- Fetches an argument when the args table is indexed. First we check -- to see if the value is memoized, and if not we try and fetch it from -- the argument tables. When we check memoization, we need to check -- metaArgs before nilArgs, as both can be non-nil at the same time. -- If the argument is not present in metaArgs, we also check whether -- pairs has been run yet. If pairs has already been run, we return nil. -- This is because all the arguments will have already been copied into -- metaArgs by the mergeArgs function, meaning that any other arguments -- must be nil. --]] if type(key) == 'string' then key = options.translate[key] end local val = metaArgs[key] if val ~= nil then return val elseif metatable.donePairs or nilArgs[key] then return nil end for _, argTable in ipairs(argTables) do local argTableVal = tidyVal(key, argTable[key]) if argTableVal ~= nil then metaArgs[key] = argTableVal return argTableVal end end nilArgs[key] = 'h' return nil end metatable.__newindex = function (t, key, val) -- This function is called when a module tries to add a new value to the -- args table, or tries to change an existing value. if type(key) == 'string' then key = options.translate[key] end if options.readOnly then error( 'could not write to argument table key "' .. tostring(key) .. '"; the table is read-only', 2 ) elseif options.noOverwrite and args[key] ~= nil then error( 'could not write to argument table key "' .. tostring(key) .. '"; overwriting existing arguments is not permitted', 2 ) elseif val == nil then --[[ -- If the argument is to be overwritten with nil, we need to erase -- the value in metaArgs, so that __index, __pairs and __ipairs do -- not use a previous existing value, if present; and we also need -- to memoize the nil in nilArgs, so that the value isn't looked -- up in the argument tables if it is accessed again. --]] metaArgs[key] = nil nilArgs[key] = 'h' else metaArgs[key] = val end end local function translatenext(invariant) local k, v = next(invariant.t, invariant.k) invariant.k = k if k == nil then return nil elseif type(k) ~= 'string' or not options.backtranslate then return k, v else local backtranslate = options.backtranslate[k] if backtranslate == nil then -- Skip this one. This is a tail call, so this won't cause stack overflow return translatenext(invariant) else return backtranslate, v end end end metatable.__pairs = function () -- Called when pairs is run on the args table. if not metatable.donePairs then mergeArgs(argTables) metatable.donePairs = true end return translatenext, { t = metaArgs } end local function inext(t, i) -- This uses our __index metamethod local v = t[i + 1] if v ~= nil then return i + 1, v end end metatable.__ipairs = function (t) -- Called when ipairs is run on the args table. return inext, t, 0 end return args end return arguments 3134ecce8429b810d445e29eae115e2ae4c36c53 Module:Category handler 828 75 165 2020-04-01T06:12:40Z Canopus >MusikAnimal 0 1 revision imported Scribunto text/plain -------------------------------------------------------------------------------- -- -- -- CATEGORY HANDLER -- -- -- -- This module implements the {{category handler}} template in Lua, -- -- with a few improvements: all namespaces and all namespace aliases -- -- are supported, and namespace names are detected automatically for -- -- the local wiki. This module requires [[Module:Namespace detect]] -- -- and [[Module:Yesno]] to be available on the local wiki. It can be -- -- configured for different wikis by altering the values in -- -- [[Module:Category handler/config]], and pages can be blacklisted -- -- from categorisation by using [[Module:Category handler/blacklist]]. -- -- -- -------------------------------------------------------------------------------- -- Load required modules local yesno = require('Module:Yesno') -- Lazily load things we don't always need local mShared, mappings local p = {} -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- local function trimWhitespace(s, removeBlanks) if type(s) ~= 'string' then return s end s = s:match('^%s*(.-)%s*$') if removeBlanks then if s ~= '' then return s else return nil end else return s end end -------------------------------------------------------------------------------- -- CategoryHandler class -------------------------------------------------------------------------------- local CategoryHandler = {} CategoryHandler.__index = CategoryHandler function CategoryHandler.new(data, args) local obj = setmetatable({ _data = data, _args = args }, CategoryHandler) -- Set the title object do local pagename = obj:parameter('demopage') local success, titleObj if pagename then success, titleObj = pcall(mw.title.new, pagename) end if success and titleObj then obj.title = titleObj if titleObj == mw.title.getCurrentTitle() then obj._usesCurrentTitle = true end else obj.title = mw.title.getCurrentTitle() obj._usesCurrentTitle = true end end -- Set suppression parameter values for _, key in ipairs{'nocat', 'categories'} do local value = obj:parameter(key) value = trimWhitespace(value, true) obj['_' .. key] = yesno(value) end do local subpage = obj:parameter('subpage') local category2 = obj:parameter('category2') if type(subpage) == 'string' then subpage = mw.ustring.lower(subpage) end if type(category2) == 'string' then subpage = mw.ustring.lower(category2) end obj._subpage = trimWhitespace(subpage, true) obj._category2 = trimWhitespace(category2) -- don't remove blank values end return obj end function CategoryHandler:parameter(key) local parameterNames = self._data.parameters[key] local pntype = type(parameterNames) if pntype == 'string' or pntype == 'number' then return self._args[parameterNames] elseif pntype == 'table' then for _, name in ipairs(parameterNames) do local value = self._args[name] if value ~= nil then return value end end return nil else error(string.format( 'invalid config key "%s"', tostring(key) ), 2) end end function CategoryHandler:isSuppressedByArguments() return -- See if a category suppression argument has been set. self._nocat == true or self._categories == false or ( self._category2 and self._category2 ~= self._data.category2Yes and self._category2 ~= self._data.category2Negative ) -- Check whether we are on a subpage, and see if categories are -- suppressed based on our subpage status. or self._subpage == self._data.subpageNo and self.title.isSubpage or self._subpage == self._data.subpageOnly and not self.title.isSubpage end function CategoryHandler:shouldSkipBlacklistCheck() -- Check whether the category suppression arguments indicate we -- should skip the blacklist check. return self._nocat == false or self._categories == true or self._category2 == self._data.category2Yes end function CategoryHandler:matchesBlacklist() if self._usesCurrentTitle then return self._data.currentTitleMatchesBlacklist else mShared = mShared or require('Module:Category handler/shared') return mShared.matchesBlacklist( self.title.prefixedText, mw.loadData('Module:Category handler/blacklist') ) end end function CategoryHandler:isSuppressed() -- Find if categories are suppressed by either the arguments or by -- matching the blacklist. return self:isSuppressedByArguments() or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist() end function CategoryHandler:getNamespaceParameters() if self._usesCurrentTitle then return self._data.currentTitleNamespaceParameters else if not mappings then mShared = mShared or require('Module:Category handler/shared') mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData end return mShared.getNamespaceParameters( self.title, mappings ) end end function CategoryHandler:namespaceParametersExist() -- Find whether any namespace parameters have been specified. -- We use the order "all" --> namespace params --> "other" as this is what -- the old template did. if self:parameter('all') then return true end if not mappings then mShared = mShared or require('Module:Category handler/shared') mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData end for ns, params in pairs(mappings) do for i, param in ipairs(params) do if self._args[param] then return true end end end if self:parameter('other') then return true end return false end function CategoryHandler:getCategories() local params = self:getNamespaceParameters() local nsCategory for i, param in ipairs(params) do local value = self._args[param] if value ~= nil then nsCategory = value break end end if nsCategory ~= nil or self:namespaceParametersExist() then -- Namespace parameters exist - advanced usage. if nsCategory == nil then nsCategory = self:parameter('other') end local ret = {self:parameter('all')} local numParam = tonumber(nsCategory) if numParam and numParam >= 1 and math.floor(numParam) == numParam then -- nsCategory is an integer ret[#ret + 1] = self._args[numParam] else ret[#ret + 1] = nsCategory end if #ret < 1 then return nil else return table.concat(ret) end elseif self._data.defaultNamespaces[self.title.namespace] then -- Namespace parameters don't exist, simple usage. return self._args[1] end return nil end -------------------------------------------------------------------------------- -- Exports -------------------------------------------------------------------------------- local p = {} function p._exportClasses() -- Used for testing purposes. return { CategoryHandler = CategoryHandler } end function p._main(args, data) data = data or mw.loadData('Module:Category handler/data') local handler = CategoryHandler.new(data, args) if handler:isSuppressed() then return nil end return handler:getCategories() end function p.main(frame, data) data = data or mw.loadData('Module:Category handler/data') local args = require('Module:Arguments').getArgs(frame, { wrappers = data.wrappers, valueFunc = function (k, v) v = trimWhitespace(v) if type(k) == 'number' then if v ~= '' then return v else return nil end else return v end end }) return p._main(args, data) end return p b74dd63857b24904ac452429b11213f18647471f Module:Category handler/config 828 77 169 2020-04-01T06:12:40Z Canopus >MusikAnimal 0 1 revision imported Scribunto text/plain -------------------------------------------------------------------------------- -- [[Module:Category handler]] configuration data -- -- Language-specific parameter names and values can be set here. -- -- For blacklist config, see [[Module:Category handler/blacklist]]. -- -------------------------------------------------------------------------------- local cfg = {} -- Don't edit this line. -------------------------------------------------------------------------------- -- Start configuration data -- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Parameter names -- -- These configuration items specify custom parameter names. -- -- To add one extra name, you can use this format: -- -- -- -- foo = 'parameter name', -- -- -- -- To add multiple names, you can use this format: -- -- -- -- foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'}, -- -------------------------------------------------------------------------------- cfg.parameters = { -- The nocat and categories parameter suppress -- categorisation. They are used with Module:Yesno, and work as follows: -- -- cfg.nocat: -- Result of yesno() Effect -- true Categorisation is suppressed -- false Categorisation is allowed, and -- the blacklist check is skipped -- nil Categorisation is allowed -- -- cfg.categories: -- Result of yesno() Effect -- true Categorisation is allowed, and -- the blacklist check is skipped -- false Categorisation is suppressed -- nil Categorisation is allowed nocat = 'nocat', categories = 'categories', -- The parameter name for the legacy "category2" parameter. This skips the -- blacklist if set to the cfg.category2Yes value, and suppresses -- categorisation if present but equal to anything other than -- cfg.category2Yes or cfg.category2Negative. category2 = 'category2', -- cfg.subpage is the parameter name to specify how to behave on subpages. subpage = 'subpage', -- The parameter for data to return in all namespaces. all = 'all', -- The parameter name for data to return if no data is specified for the -- namespace that is detected. other = 'other', -- The parameter name used to specify a page other than the current page; -- used for testing and demonstration. demopage = 'page', } -------------------------------------------------------------------------------- -- Parameter values -- -- These are set values that can be used with certain parameters. Only one -- -- value can be specified, like this: -- -- -- -- cfg.foo = 'value name' -- -- -------------------------------------------------------------------------------- -- The following settings are used with the cfg.category2 parameter. Setting -- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2 -- is present but equal to anything other than cfg.category2Yes or -- cfg.category2Negative then it supresses cateogrisation. cfg.category2Yes = 'yes' cfg.category2Negative = '¬' -- The following settings are used with the cfg.subpage parameter. -- cfg.subpageNo is the value to specify to not categorise on subpages; -- cfg.subpageOnly is the value to specify to only categorise on subpages. cfg.subpageNo = 'no' cfg.subpageOnly = 'only' -------------------------------------------------------------------------------- -- Default namespaces -- -- This is a table of namespaces to categorise by default. The keys are the -- -- namespace numbers. -- -------------------------------------------------------------------------------- cfg.defaultNamespaces = { [ 0] = true, -- main [ 6] = true, -- file [ 12] = true, -- help [ 14] = true, -- category [100] = true, -- portal [108] = true, -- book } -------------------------------------------------------------------------------- -- Wrappers -- -- This is a wrapper template or a list of wrapper templates to be passed to -- -- [[Module:Arguments]]. -- -------------------------------------------------------------------------------- cfg.wrappers = 'Template:Category handler' -------------------------------------------------------------------------------- -- End configuration data -- -------------------------------------------------------------------------------- return cfg -- Don't edit this line. 373cd107b13a5b00e6a1b7e66a749f12502c849d Module:Category handler/data 828 76 167 2020-04-01T06:12:41Z Canopus >MusikAnimal 0 1 revision imported Scribunto text/plain -- This module assembles data to be passed to [[Module:Category handler]] using -- mw.loadData. This includes the configuration data and whether the current -- page matches the title blacklist. local data = require('Module:Category handler/config') local mShared = require('Module:Category handler/shared') local blacklist = require('Module:Category handler/blacklist') local title = mw.title.getCurrentTitle() data.currentTitleMatchesBlacklist = mShared.matchesBlacklist( title.prefixedText, blacklist ) data.currentTitleNamespaceParameters = mShared.getNamespaceParameters( title, mShared.getParamMappings() ) return data abbc68048ff698e88dda06b64ecf384bbf583120 Module:Category handler/shared 828 78 171 2020-04-01T06:12:41Z Canopus >MusikAnimal 0 1 revision imported Scribunto text/plain -- This module contains shared functions used by [[Module:Category handler]] -- and its submodules. local p = {} function p.matchesBlacklist(page, blacklist) for i, pattern in ipairs(blacklist) do local match = mw.ustring.match(page, pattern) if match then return true end end return false end function p.getParamMappings(useLoadData) local dataPage = 'Module:Namespace detect/data' if useLoadData then return mw.loadData(dataPage).mappings else return require(dataPage).mappings end end function p.getNamespaceParameters(titleObj, mappings) -- We don't use title.nsText for the namespace name because it adds -- underscores. local mappingsKey if titleObj.isTalkPage then mappingsKey = 'talk' else mappingsKey = mw.site.namespaces[titleObj.namespace].name end mappingsKey = mw.ustring.lower(mappingsKey) return mappings[mappingsKey] or {} end return p d2d5de1a031e6ce97c242cbfa8afe7a92cb9eca5 Module:Namespace detect/config 828 63 141 2020-04-01T06:12:44Z Canopus >MusikAnimal 0 1 revision imported Scribunto text/plain -------------------------------------------------------------------------------- -- Namespace detect configuration data -- -- -- -- This module stores configuration data for Module:Namespace detect. Here -- -- you can localise the module to your wiki's language. -- -- -- -- To activate a configuration item, you need to uncomment it. This means -- -- that you need to remove the text "-- " at the start of the line. -- -------------------------------------------------------------------------------- local cfg = {} -- Don't edit this line. -------------------------------------------------------------------------------- -- Parameter names -- -- These configuration items specify custom parameter names. Values added -- -- here will work in addition to the default English parameter names. -- -- To add one extra name, you can use this format: -- -- -- -- cfg.foo = 'parameter name' -- -- -- -- To add multiple names, you can use this format: -- -- -- -- cfg.foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'} -- -------------------------------------------------------------------------------- ---- This parameter displays content for the main namespace: -- cfg.main = 'main' ---- This parameter displays in talk namespaces: -- cfg.talk = 'talk' ---- This parameter displays content for "other" namespaces (namespaces for which ---- parameters have not been specified): -- cfg.other = 'other' ---- This parameter makes talk pages behave as though they are the corresponding ---- subject namespace. Note that this parameter is used with [[Module:Yesno]]. ---- Edit that module to change the default values of "yes", "no", etc. -- cfg.subjectns = 'subjectns' ---- This parameter sets a demonstration namespace: -- cfg.demospace = 'demospace' ---- This parameter sets a specific page to compare: cfg.demopage = 'page' -------------------------------------------------------------------------------- -- Table configuration -- -- These configuration items allow customisation of the "table" function, -- -- used to generate a table of possible parameters in the module -- -- documentation. -- -------------------------------------------------------------------------------- ---- The header for the namespace column in the wikitable containing the list of ---- possible subject-space parameters. -- cfg.wikitableNamespaceHeader = 'Namespace' ---- The header for the wikitable containing the list of possible subject-space ---- parameters. -- cfg.wikitableAliasesHeader = 'Aliases' -------------------------------------------------------------------------------- -- End of configuration data -- -------------------------------------------------------------------------------- return cfg -- Don't edit this line. 0e4ff08d13c4b664d66b32c232deb129b77c1a56 Module:Namespace detect/data 828 62 139 2020-04-01T06:12:45Z Canopus >MusikAnimal 0 1 revision imported Scribunto text/plain -------------------------------------------------------------------------------- -- Namespace detect data -- -- This module holds data for [[Module:Namespace detect]] to be loaded per -- -- page, rather than per #invoke, for performance reasons. -- -------------------------------------------------------------------------------- local cfg = require('Module:Namespace detect/config') local function addKey(t, key, defaultKey) if key ~= defaultKey then t[#t + 1] = key end end -- Get a table of parameters to query for each default parameter name. -- This allows wikis to customise parameter names in the cfg table while -- ensuring that default parameter names will always work. The cfg table -- values can be added as a string, or as an array of strings. local defaultKeys = { 'main', 'talk', 'other', 'subjectns', 'demospace', 'demopage' } local argKeys = {} for i, defaultKey in ipairs(defaultKeys) do argKeys[defaultKey] = {defaultKey} end for defaultKey, t in pairs(argKeys) do local cfgValue = cfg[defaultKey] local cfgValueType = type(cfgValue) if cfgValueType == 'string' then addKey(t, cfgValue, defaultKey) elseif cfgValueType == 'table' then for i, key in ipairs(cfgValue) do addKey(t, key, defaultKey) end end cfg[defaultKey] = nil -- Free the cfg value as we don't need it any more. end local function getParamMappings() --[[ -- Returns a table of how parameter names map to namespace names. The keys -- are the actual namespace names, in lower case, and the values are the -- possible parameter names for that namespace, also in lower case. The -- table entries are structured like this: -- { -- [''] = {'main'}, -- ['wikipedia'] = {'wikipedia', 'project', 'wp'}, -- ... -- } --]] local mappings = {} local mainNsName = mw.site.subjectNamespaces[0].name mainNsName = mw.ustring.lower(mainNsName) mappings[mainNsName] = mw.clone(argKeys.main) mappings['talk'] = mw.clone(argKeys.talk) for nsid, ns in pairs(mw.site.subjectNamespaces) do if nsid ~= 0 then -- Exclude main namespace. local nsname = mw.ustring.lower(ns.name) local canonicalName = mw.ustring.lower(ns.canonicalName) mappings[nsname] = {nsname} if canonicalName ~= nsname then table.insert(mappings[nsname], canonicalName) end for _, alias in ipairs(ns.aliases) do table.insert(mappings[nsname], mw.ustring.lower(alias)) end end end return mappings end return { argKeys = argKeys, cfg = cfg, mappings = getParamMappings() } d224f42a258bc308ef3ad8cc8686cd7a4f47d005 Module:Yesno 828 39 93 2020-04-01T06:27:55Z Canopus >MusikAnimal 0 Undid revision 948472533 by [[Special:Contributions/w>Vogone|w>Vogone]] ([[User talk:w>Vogone|talk]]) Scribunto text/plain -- Function allowing for consistent treatment of boolean-like wikitext input. -- It works similarly to the template {{yesno}}. return function (val, default) -- If your wiki uses non-ascii characters for any of "yes", "no", etc., you -- should replace "val:lower()" with "mw.ustring.lower(val)" in the -- following line. val = type(val) == 'string' and val:lower() or val if val == nil then return nil elseif val == true or val == 'yes' or val == 'y' or val == 'true' or val == 't' or val == 'on' or tonumber(val) == 1 then return true elseif val == false or val == 'no' or val == 'n' or val == 'false' or val == 'f' or val == 'off' or tonumber(val) == 0 then return false else return default end end f767643e7d12126d020d88d662a3dd057817b9dc Module:No globals 828 41 97 2020-04-01T06:28:55Z Canopus >MusikAnimal 0 Undid revision 948472525 by [[Special:Contributions/w>DiBabelYurikBot|w>DiBabelYurikBot]] ([[User talk:w>DiBabelYurikBot|talk]]) Scribunto text/plain local mt = getmetatable(_G) or {} function mt.__index (t, k) if k ~= 'arg' then error('Tried to read nil global ' .. tostring(k), 2) end return nil end function mt.__newindex(t, k, v) if k ~= 'arg' then error('Tried to write global ' .. tostring(k), 2) end rawset(t, k, v) end setmetatable(_G, mt) 8ce3969f7d53b08bd00dabe4cc9780bc6afd412a Module:Category handler/blacklist 828 79 173 2020-04-18T08:48:05Z Canopus >Jo-Jo Eumerus 0 Per category talk page Scribunto text/plain -- This module contains the blacklist used by [[Module:Category handler]]. -- Pages that match Lua patterns in this list will not be categorised unless -- categorisation is explicitly requested. return { '^Main Page$', -- don't categorise the main page. -- Don't categorise the following pages or their subpages. -- "%f[/\0]" matches if the next character is "/" or the end of the string. '^Wikipedia:Cascade%-protected items%f[/\0]', '^User:UBX%f[/\0]', -- The userbox "template" space. '^User talk:UBX%f[/\0]', -- Don't categorise subpages of these pages, but allow -- categorisation of the base page. '^Wikipedia:Template index/.*$', -- Don't categorise archives. '/[aA]rchive', "^Wikipedia:Administrators' noticeboard/IncidentArchive%d+$", } 87469d7a9ef2a3c41b2bf04ae18f7c59a18fb855 Module:Footnotes/anchor id list/data 828 104 223 2020-05-23T17:06:22Z Canopus >Trappist the monk 0 Scribunto text/plain -- copied from Module:Ref info/data - maybe overkill here? -- for this application make lists from the redirect lists and force all template names first character uppercase require('Module:No globals'); --[[--------------------------< C S 1 _ T E M P L A T E _ P A T T E R N S >------------------------------------ These are patterns for cs1 templates and their redirects. These patterns exclude redirects that are vcite-like which redirects should be deleted because vcite is not cs1. ]] local cs1_template_patterns = { -- lua patterns of the cannonical names and redirects '[Cc]ite ar[Xx]iv', -- arXiv is the canonical name '[Cc]ite ArXiv', '[Cc]ite AV media', -- canonical '[Cc]ite audio', '[Cc]ite AV', '[Cc]ite AV ?Media', '[Cc]ite av media', '[Cc]ite cd', '[Cc]ite DVD', '[Cc]ite dvd', '[Cc]ite film', '[Cc]ite image', '[Cc]ite media', '[Cc]ite movie', '[Cc]ite music video', '[Cc]ite radio', '[Cc]ite song', '[Cc]ite ?video', '[Cc]ite visual', '[Cc]ite You[Tt]ube', '[Cc]ita vídeo', -- non-English redirect; TODO: tally separately? '[Cc]ite AV media notes', -- canonical '[Cc]ite album[ %-]notes', '[Cc]ite av media notes', '[Cc]ite DVD[ %-]notes', '[Cc]ite dvd%-notes', '[Cc]ite liner notes', '[Cc]ite music release notes', '[Ll]iner notes', '[Cc]ite bio[Rr]xiv', -- bioRxiv is the canonical form '[Cc]ite [Bb]ook', -- book is the canonical form '[Bb]ook cite', '[Bb]ook reference', '[Bb]ook reference url', '[Cc] book', '[Cc]it book', '[Cc]ite books', '[Cc]ite chapter', '[Cc]ite ebook', '[Cc]ite manual', '[Cc]ite page', '[Cc]ite publication', '[Cc]ite score', '[Cc]ite work', '[Cc]ite%-?book', '[Bb]okref', '[Cc]itace monografie', '[Cc]itar livro', -- non-English redirects; TODO: tally separately? '[Cc]iteer boek', '[Oo]uvrage', '[Rr]ef%-llibre', '서적 인용', '[Cc]ite citeseerx', -- canonical '[Cc]ite conference', -- canonical '[Cc]ita conferenza', '[Cc]ite proceedings', '[Cc]onference reference', -- cita conferenza is non-English; TODO: tally separately? '[Cc]ite ?encyclopedia', -- cite encyclopedia is the canonical name '[Cc]ite contribution', '[Cc]ite dic', '[Cc]ite dictionary', '[Cc]ite encyclopaedia', '[Cc]ite encyclopædia', '[Ee]ncyclopedia', '[Cc]ite [Ee]pisode', -- episode is the canonical form '[Cc]ite show', '[Cc]ite interview', -- canonical '[Cc]ite ?journal', -- cite journal is the canonical form '[Cc] journal', '[Cc]itation journal', '[Cc]ite abstract', '[Cc]ite document', '[Cc]ite Journal', '[Cc]ite journal zh', '[Cc]ite ?paper', '[Vv]cite2 journal', '[Cc]ita pubblicazione', '[Cc]itace periodika', '[Cc]itar jornal', -- non-English redirects; TODO: tally separately? '[Cc]itar publicació', '[Cc]ytuj pismo', '[Tt]idskriftsref', 'Навод из стручног часописа', '저널 인용', '[Cc]ite [Mm]agazine', -- magazine is the canonical form '[Cc]ite mag', '[Cc]ite magazine article', '[Cc]ite newsletter', '[Cc]ite periodical', '[Cc]ite mailing ?list', -- mailing list is the canonical form '[Cc]ite list', '[Cc]ite maps?', -- map is the canonical form '[Cc]ite[ %-]?news', -- cite news is the canonical form '[Cc] news', '[Cc]it news', '[Cc]itation news', '[Cc]ite article', '[Cc]ite n', '[Cc]ite new', '[Cc]ite newspaper', '[Cc]ite News', '[Cc]ite news%-q', '[Cc]ite news2', '[Cc]itenewsauthor', '[Cc]ute news', '[Cc]itar notícia', '[Hh]aber kaynağı', '[Tt]idningsref', 'استشهاد بخبر', -- non-English redirects; TODO: tally separately? '뉴스 인용', '[Cc]ite newsgroup', -- canonical '[Cc]ite usenet', '[Cc]ite podcast', -- canonical '[Cc]ite [Pp]ress release', -- press release is the canonical form '[Cc]ite media release', '[Cc]ite news release', '[Cc]ite pr', '[Cc]ite press', '[Cc]ite press release\.', '[Cc]ite press[%-]?release', '[Cc]ite report', -- canonical '[Cc]ite serial', -- canonical '[Cc]ite sign', -- canonical '[Cc]ite plaque', '[Cc]ite speech', -- canonical '[Cc]ite ssrn', -- canonical '[Cc]ite SSRN', '[Cc]ite tech ?report', -- techreport is the canonical form '[Cc]ite standard', '[Cc]ite technical report', '[Tt]echrep reference', '[Cc]ite thesis', -- canonical '[Cc]ite dissertation', '[Cc]itar tese', -- non-English redirect; TODO: tally separately? '[Cc]ite [Ww]eb', -- web is the canonical form '[Cc] web', '[Cc]it web', '[Cc]ite blog', '[Cc]ite URL', '[Cc]ite url', '[Cc]ite w', '[Cc]ite wb', '[Cc]ite we', '[Cc]ite web\.', '[Cc]ite webpage', '[Cc]ite website', '[Cc]ite website article', '[Cc]ite%-?web', '[Cc]itweb', '[Cc]w', '[Rr]ef web', '[Ww]eb citation', '[Ww]eb cite', '[Ww]eb link', '[Ww]eb[ %-]reference', '[Ww]eblink', '[Cc]hú thích web', '[Cc]ita web', '[Cc]itace elektronické monografie', -- non-English redirects; TODO: tally separately? '[Cc]itat web', 'مرجع ويب', 'یادکرد وب', '웹 인용', } --[[--------------------------< C S 2 _ T E M P L A T E _ P A T T E R N S >------------------------------------ These are patterns for cs2 templates redirects. ]] local cs2_template_patterns = { -- lua patterns of the cannonical names and redirects '[Cc]itation', '[Cc]ite', '[Cc]ite citation', '[Cc]ite study', '[Cc]ite [Tt]echnical standard', } --[[--------------------------< V C I T E _ T E M P L A T E _ P A T T E R N S >-------------------------------- These are patterns for Vcite-family templates and their redirects. ]] local vcite_template_patterns = { '[Vv]cite book', -- canonical '[Vv]ancite book', '[Vv]ancite report', '[Vv]cite encyclopedia', '[Vv]cite report', '[Vv]cite journal', -- canonical '[Cc]it journal', '[Cc]it paper', '[Vv]ancite journal', '[Vv]cite paper', '[Vv]cite news', -- canonical '[Vv]ancite news', '[Vv]cite web', -- canonical '[Vv]ancite web', } --[[--------------------------< H A R V C _ T E M P L A T E _ P A T T E R N S >-------------------------------- These are patterns for the harvc template and its redirects. ]] local harvc_template_patterns = { '[Hh]arvc', -- canonical '[Cc]itec', } --[[--------------------------< C S 1 _ L I K E _ T E M P L A T E _ P A T T E R N S >-------------------------- These are patterns for miscellaneous templates and their redirects that 'look like' cs1 templates (begin with cite ...) Because they 'look like' cs1 templates they are handled as if they were cs1 templates. These templates are NOT wrapper templates; names and dates are always to be extracted from the article instantiation of the template. ]] local cs1_like_template_patterns = { '[Cc]ite LSA', -- canonical } --[[--------------------------< W I K I C I T E _ T E M P L A T E _ P A T T E R N S >-------------------------- These are patterns for the wikicite template and its redirects. ]] local wikicite_template_patterns = { '[Ww]ikicite', -- canonical } --[[--------------------------< A N C H O R _ T E M P L A T E _ P A T T E R N S >------------------------------ These are patterns for the anchor template and its redirects. ]] local anchor_template_patterns = { '[Aa]nchors?', -- anchor is canonical form '[Aa]nchor for redirect', '[Aa]nchro', '[Aa]ncor', } --[[--------------------------< S F N _ W H I T E L I S T _ P A T T E R N S >---------------------------------- These are patterns for the anchor template and its redirects. ]] local sfn_whitelist_patterns = { '[Ss]fn whitelist', -- canonical '[Hh]arv whitelist', } --[[--------------------------< K N O W N _ T E M P L A T E S >------------------------------------------------ These tables are created from the *_template_patterns tables. To make these tables, entries in the source tables are evaluated to replace lua patterns with the appropriate characters to create names for the output tables. First charqacter is always uppercase For example: [Cc]ite ar[Xx]iv becomes Cite arXiv Cite arxiv ]] local known_templates_cs12 = {}; -- the exported tables local known_templates_vcite = {}; local known_templates_harvc = {}; local known_templates_wikicite = {}; local known_templates_anchor = {}; local known_templates_sfn_whitelist = {}; local function add_stripped (list, name) if not list[name] then list[name] = true; end end local function pattern_convert (pattern, list) local lead, tail, c, l, name; local first_char_patterns = { '^%[(%a)%a%]', -- leading character (usually uppercase) '^%[%a(%a)%]', -- leading character (usually lowercase) } c = tostring (pattern:match ('%u')); -- tostring() required because I don't know why; lua chokes complaining that c is not a string name = pattern:gsub ('^%[%a%a%]', c); -- replace bracketed first character [Xx] with selected character from the match if name:match ('(.-)%[(%a)(%a)%](.*)') then -- mixed case optional letters lead, c, l, tail = name:match ('(.-)%[(%a)(%a)%](.*)'); add_stripped (list, lead .. c .. tail); -- uppercase add_stripped (list, lead .. l .. tail); -- lowercase elseif name:match ('^([^%[]+)(%[ %%%-%]%?)(.+)$') then -- [ %-]? lead, c, tail = name:match ('^([^%[]+)(%[ %%%-%]%?)(.+)$'); add_stripped (list, lead .. tail); -- neither char add_stripped (list, lead .. ' ' .. tail); -- space add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^([^%[]+)(%[%%%-%]%?)(.+)$') then -- [%-]? lead, c, tail = name:match ('^([^%[]+)(%[%%%-%]%?)(.+)$'); add_stripped (list, lead .. tail); -- no hyphen add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^([^%[]+)(%[ %%%-%])(.+)$') then -- [ %-] lead, c, tail = name:match ('^([^%[]+)(%[ %%%-%])(.+)$'); add_stripped (list, lead .. ' ' .. tail); -- space add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^([^%?]+)(%%%-%?)(.+)$') then -- %-? lead, c, tail = name:match ('^([^%?]+)(%%%-%?)(.+)$'); add_stripped (list, lead .. tail); -- no hyphen add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^(.-)(%%%-)(.+)$') then -- %- lead, c, tail = name:match ('^(.-)(%%%-)(.+)$'); add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^(.-)(.)%?(.*)$') then -- .? lead, c, tail = name:match ('^(.-)(.)%?(.*)$'); add_stripped (list, lead .. tail); -- no character add_stripped (list, lead .. c .. tail); -- character else add_stripped (list, name); -- no patterns so save as is end end for _, t in ipairs ({ {cs1_template_patterns, known_templates_cs12}, {cs2_template_patterns, known_templates_cs12}, {cs1_like_template_patterns, known_templates_cs12}, {vcite_template_patterns, known_templates_vcite}, {harvc_template_patterns, known_templates_harvc}, {wikicite_template_patterns, known_templates_wikicite}, {anchor_template_patterns, known_templates_anchor}, {sfn_whitelist_patterns, known_templates_sfn_whitelist}, }) do for _, pattern in ipairs (t[1]) do -- for each patern in *_template_patterns pattern_convert (pattern, t[2]) -- convert and store in known_templates_* end end --[[--------------------------< E X P O R T S >---------------------------------------------------------------- ]] return { known_templates_anchor = known_templates_anchor, known_templates_cs12 = known_templates_cs12, known_templates_harvc = known_templates_harvc, known_templates_vcite = known_templates_vcite, known_templates_wikicite = known_templates_wikicite, known_templates_sfn_whitelist = known_templates_sfn_whitelist, } 6267b1029a020fb98adfa02a74118ae31897ac81 Module:Other uses 828 116 247 2020-06-01T23:06:08Z Canopus >Nihiltres 0 Removed p.otheruses2 function per its template's deletion Scribunto text/plain local mHatnote = require('Module:Hatnote') local mHatlist = require('Module:Hatnote list') local mArguments --initialize lazily local mTableTools --initialize lazily local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local p = {} -- Produces standard {{other uses}} implementation function p.otheruses(frame) mArguments = require('Module:Arguments') mTableTools = require('Module:TableTools') local args = mTableTools.compressSparseArray(mArguments.getArgs(frame)) local title = mw.title.getCurrentTitle().prefixedText return p._otheruses(args, {title=title}) end --Implements "other [x]" templates with otherText supplied at invocation function p.otherX(frame) mArguments = require('Module:Arguments') mTableTools = require('Module:TableTools') local x = frame.args[1] local args = mTableTools.compressSparseArray( mArguments.getArgs(frame, {parentOnly = true}) ) local options = { title = mw.title.getCurrentTitle().prefixedText, otherText = x } return p._otheruses(args, options) end -- Main generator function p._otheruses(args, options) --Type-checks and defaults checkType('_otheruses', 1, args, 'table', true) args = args or {} checkType('_otheruses', 2, options, 'table') if not (options.defaultPage or options.title) then error('No default title data provided in "_otheruses" options table', 2) end local emptyArgs = true for k, v in pairs(args) do if type(k) == 'number' then emptyArgs = false break end end if emptyArgs then args = { options.defaultPage or mHatnote.disambiguate(options.title, options.disambiguator) } end --Generate and return hatnote local text = mHatlist.forSeeTableToString({{ use = options.otherText and "other " .. options.otherText or nil, pages = args }}) return mHatnote._hatnote(text) end return p 2497cafae11ffa785bced56bc9f3853cf3bce7b1 Module:Pagetype 828 59 133 2020-06-18T21:22:08Z Canopus >RexxS 0 add caps parameter per talk request Scribunto text/plain -------------------------------------------------------------------------------- -- -- -- PAGETYPE -- -- -- -- This is a meta-module intended to replace {{pagetype}} and similar -- -- templates. It automatically detects namespaces, and allows for a -- -- great deal of customisation. It can easily be ported to other -- -- wikis by changing the values in the [[Module:Pagetype/config]]. -- -- -- -------------------------------------------------------------------------------- -- Load config. local cfg = mw.loadData('Module:Pagetype/config') -- Load required modules. local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') local nsDetectModule = require('Module:Namespace detect') local nsDetect = nsDetectModule._main local getParamMappings = nsDetectModule.getParamMappings local getPageObject = nsDetectModule.getPageObject local p = {} local function shallowCopy(t) -- Makes a shallow copy of a table. local ret = {} for k, v in pairs(t) do ret[k] = v end return ret end local function checkPagetypeInput(namespace, val) -- Checks to see whether we need the default value for the given namespace, -- and if so gets it from the pagetypes table. -- The yesno function returns true/false for "yes", "no", etc., and returns -- val for other input. local ret = yesno(val, val) if ret and type(ret) ~= 'string' then ret = cfg.pagetypes[namespace] end return ret end local function getPagetypeFromClass(class, param, aliasTable, default) -- Gets the pagetype from a class specified from the first positional -- parameter. param = yesno(param, param) if param ~= false then -- No check if specifically disallowed. for _, alias in ipairs(aliasTable) do if class == alias then if type(param) == 'string' then return param else return default end end end end end local function getNsDetectValue(args) -- Builds the arguments to pass to [[Module:Namespace detect]] and returns -- the result. -- Get the default values. local ndArgs = {} local defaultns = args[cfg.defaultns] if defaultns == cfg.defaultnsAll then ndArgs = shallowCopy(cfg.pagetypes) else local defaultnsArray if defaultns == cfg.defaultnsExtended then defaultnsArray = cfg.extendedNamespaces elseif defaultns == cfg.defaultnsNone then defaultnsArray = {} else defaultnsArray = cfg.defaultNamespaces end for _, namespace in ipairs(defaultnsArray) do ndArgs[namespace] = cfg.pagetypes[namespace] end end --[[ -- Add custom values passed in from the arguments. These overwrite the -- defaults. The possible argument names are fetched from -- Module:Namespace detect automatically in case new namespaces are -- added. Although we accept namespace aliases as parameters, we only pass -- the local namespace name as a parameter to Module:Namespace detect. -- This means that the "image" parameter can overwrite defaults for the -- File: namespace, which wouldn't work if we passed the parameters through -- separately. --]] local mappings = getParamMappings() for ns, paramAliases in pairs(mappings) do -- Copy the aliases table, as # doesn't work with tables returned from -- mw.loadData. paramAliases = shallowCopy(paramAliases) local paramName = paramAliases[1] -- Iterate backwards along the array so that any values for the local -- namespace names overwrite those for namespace aliases. for i = #paramAliases, 1, -1 do local paramAlias = paramAliases[i] local ndArg = checkPagetypeInput(paramAlias, args[paramAlias]) if ndArg == false then -- If any arguments are false, convert them to nil to protect -- against breakage by future changes to -- [[Module:Namespace detect]]. ndArgs[paramName] = nil elseif ndArg then ndArgs[paramName] = ndArg end end end -- Check for disambiguation-class and N/A-class pages in mainspace. if ndArgs.main then local class = args[1] if type(class) == 'string' then -- Put in lower case so e.g. "Dab" and "dab" will both match. class = mw.ustring.lower(class) end local dab = getPagetypeFromClass( class, args[cfg.dab], cfg.dabAliases, cfg.dabDefault ) if dab then ndArgs.main = dab else local na = getPagetypeFromClass( class, args[cfg.na], cfg.naAliases, cfg.naDefault ) if na then ndArgs.main = na end end end -- If there is no talk value specified, use the corresponding subject -- namespace for talk pages. if not ndArgs.talk then ndArgs.subjectns = true end -- Add the fallback value. This can also be customised, but it cannot be -- disabled. local other = args[cfg.other] -- We will ignore true/false/nil results from yesno here, but using it -- anyway for consistency. other = yesno(other, other) if type(other) == 'string' then ndArgs.other = other else ndArgs.other = cfg.otherDefault end -- Allow custom page values. ndArgs.page = args.page return nsDetect(ndArgs) end local function detectRedirects(args) local redirect = args[cfg.redirect] -- The yesno function returns true/false for "yes", "no", etc., and returns -- redirect for other input. redirect = yesno(redirect, redirect) if redirect == false then -- Detect redirects unless they have been explicitly disallowed with -- "redirect=no" or similar. return end local pageObject = getPageObject(args.page) -- If we are using subject namespaces elsewhere, do so here as well. if pageObject and not yesno(args.talk, true) and args[cfg.defaultns] ~= cfg.defaultnsAll then pageObject = getPageObject( pageObject.subjectNsText .. ':' .. pageObject.text ) end -- Allow custom values for redirects. if pageObject and pageObject.isRedirect then if type(redirect) == 'string' then return redirect else return cfg.redirectDefault end end end function p._main(args) local redirect = detectRedirects(args) local pagetype = "" if redirect then pagetype = redirect else pagetype = getNsDetectValue(args) end if yesno(args.plural, false) then if cfg.irregularPlurals[pagetype] then pagetype = cfg.irregularPlurals[pagetype] else pagetype = pagetype .. cfg.plural -- often 's' end end if yesno(args.caps, false) then pagetype = mw.ustring.upper(mw.ustring.sub(pagetype, 1, 1)) .. mw.ustring.sub(pagetype, 2) end return pagetype end function p.main(frame) local args = getArgs(frame) return p._main(args) end return p 210524e0c60e3354325aea88c508e94423ad228d Template:SfnRef 10 101 217 2020-07-04T15:54:11Z Canopus >Ahecht 0 safesubst<noinclude />: wikitext text/x-wiki {{safesubst<noinclude />:#invoke:Footnotes|sfnref}}<noinclude> {{documentation}} </noinclude> 56e03dd26fcd9edbe71a96b5c5c84198863b964b Module:String 828 71 157 2020-08-02T15:49:42Z Canopus >RexxS 0 separate annotations for str.match from those for str._match Scribunto text/plain --[[ This module is intended to provide access to basic string functions. Most of the functions provided here can be invoked with named parameters, unnamed parameters, or a mixture. If named parameters are used, Mediawiki will automatically remove any leading or trailing whitespace from the parameter. Depending on the intended use, it may be advantageous to either preserve or remove such whitespace. Global options ignore_errors: If set to 'true' or 1, any error condition will result in an empty string being returned rather than an error message. error_category: If an error occurs, specifies the name of a category to include with the error message. The default category is [Category:Errors reported by Module String]. no_category: If set to 'true' or 1, no category will be added if an error is generated. Unit tests for this module are available at Module:String/tests. ]] local str = {} --[[ len This function returns the length of the target string. Usage: {{#invoke:String|len|target_string|}} OR {{#invoke:String|len|s=target_string}} Parameters s: The string whose length to report If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from the target string. ]] function str.len( frame ) local new_args = str._getParameters( frame.args, {'s'} ) local s = new_args['s'] or '' return mw.ustring.len( s ) end --[[ sub This function returns a substring of the target string at specified indices. Usage: {{#invoke:String|sub|target_string|start_index|end_index}} OR {{#invoke:String|sub|s=target_string|i=start_index|j=end_index}} Parameters s: The string to return a subset of i: The fist index of the substring to return, defaults to 1. j: The last index of the string to return, defaults to the last character. The first character of the string is assigned an index of 1. If either i or j is a negative value, it is interpreted the same as selecting a character by counting from the end of the string. Hence, a value of -1 is the same as selecting the last character of the string. If the requested indices are out of range for the given string, an error is reported. ]] function str.sub( frame ) local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } ) local s = new_args['s'] or '' local i = tonumber( new_args['i'] ) or 1 local j = tonumber( new_args['j'] ) or -1 local len = mw.ustring.len( s ) -- Convert negatives for range checking if i < 0 then i = len + i + 1 end if j < 0 then j = len + j + 1 end if i > len or j > len or i < 1 or j < 1 then return str._error( 'String subset index out of range' ) end if j < i then return str._error( 'String subset indices out of order' ) end return mw.ustring.sub( s, i, j ) end --[[ This function implements that features of {{str sub old}} and is kept in order to maintain these older templates. ]] function str.sublength( frame ) local i = tonumber( frame.args.i ) or 0 local len = tonumber( frame.args.len ) return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) ) end --[[ _match This function returns a substring from the source string that matches a specified pattern. It is exported for use in other modules Usage: strmatch = require("Module:String")._match sresult = strmatch( s, pattern, start, match, plain, nomatch ) Parameters s: The string to search pattern: The pattern or string to find within the string start: The index within the source string to start the search. The first character of the string has index 1. Defaults to 1. match: In some cases it may be possible to make multiple matches on a single string. This specifies which match to return, where the first match is match= 1. If a negative number is specified then a match is returned counting from the last match. Hence match = -1 is the same as requesting the last match. Defaults to 1. plain: A flag indicating that the pattern should be understood as plain text. Defaults to false. nomatch: If no match is found, output the "nomatch" value rather than an error. For information on constructing Lua patterns, a form of [regular expression], see: * http://www.lua.org/manual/5.1/manual.html#5.4.1 * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns ]] -- This sub-routine is exported for use in other modules function str._match( s, pattern, start, match_index, plain_flag, nomatch ) if s == '' then return str._error( 'Target string is empty' ) end if pattern == '' then return str._error( 'Pattern string is empty' ) end start = tonumber(start) or 1 if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then return str._error( 'Requested start is out of range' ) end if match_index == 0 then return str._error( 'Match index is out of range' ) end if plain_flag then pattern = str._escapePattern( pattern ) end local result if match_index == 1 then -- Find first match is simple case result = mw.ustring.match( s, pattern, start ) else if start > 1 then s = mw.ustring.sub( s, start ) end local iterator = mw.ustring.gmatch(s, pattern) if match_index > 0 then -- Forward search for w in iterator do match_index = match_index - 1 if match_index == 0 then result = w break end end else -- Reverse search local result_table = {} local count = 1 for w in iterator do result_table[count] = w count = count + 1 end result = result_table[ count + match_index ] end end if result == nil then if nomatch == nil then return str._error( 'Match not found' ) else return nomatch end else return result end end --[[ match This function returns a substring from the source string that matches a specified pattern. Usage: {{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}} OR {{#invoke:String|match|s=source_string|pattern=pattern_string|start=start_index |match=match_number|plain=plain_flag|nomatch=nomatch_output}} Parameters s: The string to search pattern: The pattern or string to find within the string start: The index within the source string to start the search. The first character of the string has index 1. Defaults to 1. match: In some cases it may be possible to make multiple matches on a single string. This specifies which match to return, where the first match is match= 1. If a negative number is specified then a match is returned counting from the last match. Hence match = -1 is the same as requesting the last match. Defaults to 1. plain: A flag indicating that the pattern should be understood as plain text. Defaults to false. nomatch: If no match is found, output the "nomatch" value rather than an error. If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from each string. In some circumstances this is desirable, in other cases one may want to preserve the whitespace. If the match_number or start_index are out of range for the string being queried, then this function generates an error. An error is also generated if no match is found. If one adds the parameter ignore_errors=true, then the error will be suppressed and an empty string will be returned on any failure. For information on constructing Lua patterns, a form of [regular expression], see: * http://www.lua.org/manual/5.1/manual.html#5.4.1 * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns ]] -- This is the entry point for #invoke:String|match function str.match( frame ) local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} ) local s = new_args['s'] or '' local start = tonumber( new_args['start'] ) or 1 local plain_flag = str._getBoolean( new_args['plain'] or false ) local pattern = new_args['pattern'] or '' local match_index = math.floor( tonumber(new_args['match']) or 1 ) local nomatch = new_args['nomatch'] return str._match( s, pattern, start, match_index, plain_flag, nomatch ) end --[[ pos This function returns a single character from the target string at position pos. Usage: {{#invoke:String|pos|target_string|index_value}} OR {{#invoke:String|pos|target=target_string|pos=index_value}} Parameters target: The string to search pos: The index for the character to return If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from the target string. In some circumstances this is desirable, in other cases one may want to preserve the whitespace. The first character has an index value of 1. If one requests a negative value, this function will select a character by counting backwards from the end of the string. In other words pos = -1 is the same as asking for the last character. A requested value of zero, or a value greater than the length of the string returns an error. ]] function str.pos( frame ) local new_args = str._getParameters( frame.args, {'target', 'pos'} ) local target_str = new_args['target'] or '' local pos = tonumber( new_args['pos'] ) or 0 if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then return str._error( 'String index out of range' ) end return mw.ustring.sub( target_str, pos, pos ) end --[[ str_find This function duplicates the behavior of {{str_find}}, including all of its quirks. This is provided in order to support existing templates, but is NOT RECOMMENDED for new code and templates. New code is recommended to use the "find" function instead. Returns the first index in "source" that is a match to "target". Indexing is 1-based, and the function returns -1 if the "target" string is not present in "source". Important Note: If the "target" string is empty / missing, this function returns a value of "1", which is generally unexpected behavior, and must be accounted for separatetly. ]] function str.str_find( frame ) local new_args = str._getParameters( frame.args, {'source', 'target'} ) local source_str = new_args['source'] or '' local target_str = new_args['target'] or '' if target_str == '' then return 1 end local start = mw.ustring.find( source_str, target_str, 1, true ) if start == nil then start = -1 end return start end --[[ find This function allows one to search for a target string or pattern within another string. Usage: {{#invoke:String|find|source_str|target_string|start_index|plain_flag}} OR {{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}} Parameters source: The string to search target: The string or pattern to find within source start: The index within the source string to start the search, defaults to 1 plain: Boolean flag indicating that target should be understood as plain text and not as a Lua style regular expression, defaults to true If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from the parameter. In some circumstances this is desirable, in other cases one may want to preserve the whitespace. This function returns the first index >= "start" where "target" can be found within "source". Indices are 1-based. If "target" is not found, then this function returns 0. If either "source" or "target" are missing / empty, this function also returns 0. This function should be safe for UTF-8 strings. ]] function str.find( frame ) local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } ) local source_str = new_args['source'] or '' local pattern = new_args['target'] or '' local start_pos = tonumber(new_args['start']) or 1 local plain = new_args['plain'] or true if source_str == '' or pattern == '' then return 0 end plain = str._getBoolean( plain ) local start = mw.ustring.find( source_str, pattern, start_pos, plain ) if start == nil then start = 0 end return start end --[[ replace This function allows one to replace a target string or pattern within another string. Usage: {{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}} OR {{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string| count=replacement_count|plain=plain_flag}} Parameters source: The string to search pattern: The string or pattern to find within source replace: The replacement text count: The number of occurences to replace, defaults to all. plain: Boolean flag indicating that pattern should be understood as plain text and not as a Lua style regular expression, defaults to true ]] function str.replace( frame ) local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } ) local source_str = new_args['source'] or '' local pattern = new_args['pattern'] or '' local replace = new_args['replace'] or '' local count = tonumber( new_args['count'] ) local plain = new_args['plain'] or true if source_str == '' or pattern == '' then return source_str end plain = str._getBoolean( plain ) if plain then pattern = str._escapePattern( pattern ) replace = mw.ustring.gsub( replace, "%%", "%%%%" ) --Only need to escape replacement sequences. end local result if count ~= nil then result = mw.ustring.gsub( source_str, pattern, replace, count ) else result = mw.ustring.gsub( source_str, pattern, replace ) end return result end --[[ simple function to pipe string.rep to templates. ]] function str.rep( frame ) local repetitions = tonumber( frame.args[2] ) if not repetitions then return str._error( 'function rep expects a number as second parameter, received "' .. ( frame.args[2] or '' ) .. '"' ) end return string.rep( frame.args[1] or '', repetitions ) end --[[ escapePattern This function escapes special characters from a Lua string pattern. See [1] for details on how patterns work. [1] https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns Usage: {{#invoke:String|escapePattern|pattern_string}} Parameters pattern_string: The pattern string to escape. ]] function str.escapePattern( frame ) local pattern_str = frame.args[1] if not pattern_str then return str._error( 'No pattern string specified' ) end local result = str._escapePattern( pattern_str ) return result end --[[ count This function counts the number of occurrences of one string in another. ]] function str.count(frame) local args = str._getParameters(frame.args, {'source', 'pattern', 'plain'}) local source = args.source or '' local pattern = args.pattern or '' local plain = str._getBoolean(args.plain or true) if plain then pattern = str._escapePattern(pattern) end local _, count = mw.ustring.gsub(source, pattern, '') return count end --[[ endswith This function determines whether a string ends with another string. ]] function str.endswith(frame) local args = str._getParameters(frame.args, {'source', 'pattern'}) local source = args.source or '' local pattern = args.pattern or '' if pattern == '' then -- All strings end with the empty string. return "yes" end if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then return "yes" else return "" end end --[[ join Join all non empty arguments together; the first argument is the separator. Usage: {{#invoke:String|join|sep|one|two|three}} ]] function str.join(frame) local args = {} local sep for _, v in ipairs( frame.args ) do if sep then if v ~= '' then table.insert(args, v) end else sep = v end end return table.concat( args, sep or '' ) end --[[ Helper function that populates the argument list given that user may need to use a mix of named and unnamed parameters. This is relevant because named parameters are not identical to unnamed parameters due to string trimming, and when dealing with strings we sometimes want to either preserve or remove that whitespace depending on the application. ]] function str._getParameters( frame_args, arg_list ) local new_args = {} local index = 1 local value for _, arg in ipairs( arg_list ) do value = frame_args[arg] if value == nil then value = frame_args[index] index = index + 1 end new_args[arg] = value end return new_args end --[[ Helper function to handle error messages. ]] function str._error( error_str ) local frame = mw.getCurrentFrame() local error_category = frame.args.error_category or 'Errors reported by Module String' local ignore_errors = frame.args.ignore_errors or false local no_category = frame.args.no_category or false if str._getBoolean(ignore_errors) then return '' end local error_str = '<strong class="error">String Module Error: ' .. error_str .. '</strong>' if error_category ~= '' and not str._getBoolean( no_category ) then error_str = '[[Category:' .. error_category .. ']]' .. error_str end return error_str end --[[ Helper Function to interpret boolean strings ]] function str._getBoolean( boolean_str ) local boolean_value if type( boolean_str ) == 'string' then boolean_str = boolean_str:lower() if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0' or boolean_str == '' then boolean_value = false else boolean_value = true end elseif type( boolean_str ) == 'boolean' then boolean_value = boolean_str else error( 'No boolean value found' ) end return boolean_value end --[[ Helper function that escapes all pattern characters so that they will be treated as plain text. ]] function str._escapePattern( pattern_str ) return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ) end return str 6df794dd52434e0f6a372c9918f5a9dedd15f579 Template:SDcat 10 68 151 2020-08-07T18:02:31Z Canopus >MusikBot II 0 Protected "[[Template:SDcat]]": [[Wikipedia:High-risk templates|High-risk template or module]] ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) wikitext text/x-wiki <includeonly>{{#invoke:SDcat |setCat}}</includeonly><noinclude> {{documentation}} </noinclude> 8c6e8783ddb0dc699d6fb60370db97b73725b9a6 Template:Convert 10 95 205 2020-08-09T22:52:24Z Canopus >Bsherr 0 adding comment wikitext text/x-wiki <includeonly>{{{{{♥|safesubst:}}}#invoke:convert|convert}}</includeonly><noinclude> {{documentation}} <!-- Add categories to the /doc subpage, interwikis to Wikidata, not here --> </noinclude> 952ac4080dc4a427c4a65db9951c8a4f4c91c626 Module:SDcat 828 72 159 2020-08-16T17:20:37Z Canopus >RexxS 0 if no connection to Wikidata, then do nothing Scribunto text/plain --[[ SDcat Module to check whether local short description matches that on Wikidata --]] local p = {} ------------------------------------------------------------------------------- --[[ setCat has the qid of a Wikidata entity passed as |qid= (it defaults to the associated qid of the current article if omitted) and the local short description passed as |sd= It returns a category if there is an associated Wikidata entity. It returns one of the following tracking categories, as appropriate: * Category:Short description matches Wikidata (case-insensitive) * Category:Short description is different from Wikidata * Category:Short description with empty Wikidata description For testing purposes, a link prefix |lp= may be set to ":" to make the categories visible. --]] -- function exported for use in other modules -- (local short description, Wikidata entity-ID, link prefix) p._setCat = function(sdesc, itemID, lp) if not mw.wikibase then return nil end if itemID == "" then itemID = nil end -- Wikidata description field local wdesc = (mw.wikibase.getDescription(itemID) or ""):lower() if wdesc == "" then return "[[" .. lp .. "Category:Short description with empty Wikidata description]]" elseif wdesc == sdesc then return "[[" .. lp .. "Category:Short description matches Wikidata]]" else return "[[" .. lp .. "Category:Short description is different from Wikidata]]" end end -- function exported for call from #invoke p.setCat = function(frame) local args if frame.args.sd then args = frame.args else args = frame:getParent().args end -- local short description local sdesc = mw.text.trim(args.sd or ""):lower() -- Wikidata entity-ID local itemID = mw.text.trim(args.qid or "") -- link prefix, strip quotes local lp = mw.text.trim(args.lp or ""):gsub('"', '') return p._setCat(sdesc, itemID, lp) end return p 6c19ac0f72c79a618eb105808f74701376bb2b38 Module:Portal/images/o 828 136 287 2020-09-15T07:16:03Z Canopus >Northamerica1000 0 Addition: ["ocean"] = "Waves in pacifica 1.jpg|alt=icon",. rw: ["oceans"] = "Waves in pacifica 1.jpg|alt=icon", Scribunto text/plain --[==[ This is the "O" list of portal image names. It contains a list of portal images for use with [[Module:Portal]] -- for portal names that start with the letter "O". For aliases to existing portal names, and for portal names that -- start with other letters, please use the appropriate page from the following list: -- [[Module:Portal/images/a]] - for portal names beginning with "A". -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/s]] - for portal names beginning with "S". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- [[Module:Portal/images/aliases]] - for adding aliases for existing portal names. Use this page for variations -- in spelling and diacritics, etc., no matter what letter the portal begins with. -- When adding entries, please use alphabetical order. The format of the images table entries is as follows: -- ["portal name"] = "image.svg", -- The portal name should be the name of your portal, in lower case. For example, the portal name for -- "Portal:United Kingdom" would be "united kingdom". The image name should be capitalised normally, and the "File:" -- namespace prefix should be omitted. ]==] return { ["oaxaca"] = "Flag of Oaxaca.svg|border|link=|alt=flag", ["occult"] = "Pentacle 2.svg|link=|alt=", ["oceania"] = "大洋.png|alt=icon", ["ocean"] = "Waves in pacifica 1.jpg|alt=icon", ["oceans"] = "Waves in pacifica 1.jpg|alt=icon", ["odense"] = "Coat of arms of Odense.svg|alt=icon", ["odessa"] = "Flag of Odessa.svg|alt=flag", ["odisha"] = "Seal of Odisha.png|link=|alt=seal", ["ohio"] = "Flag of Ohio.svg|link=|alt=flag", ["ohio wesleyan university"] = "ElliottHallOWU.jpg|link=|alt=photo", ["oklahoma"] = "Flag of Oklahoma.svg|border|link=|alt=flag", ["olives"] = "NCI 2 green olives.jpg|link=|alt=", ["olympic games"] = "Olympic Rings.svg|link=|alt=", ["olympics"] = "Olympic Rings.svg|link=|alt=", ["omaha"] = "Flag of Omaha, Nebraska.jpg|link=|alt=flag", ["oman"] = "Flag of Oman.svg|border|link=|alt=flag", ["ontario"] = "Flag of Ontario.svg|border|link=|alt=flag", ["ontario regions"] = "Ontario-flag-contour.png|link=|alt=", ["opera"] = "Operalogo.svg|alt=icon", ["oregon"] = "Flag of Oregon.svg|border|link=|alt=flag", ["organic chemistry"] = "Covalent.svg|alt=icon", ["organized labour"] = "Syndicalism.svg|alt=icon", ["oriental orthodoxy"] = "CopticCross.jpg|link=|alt=", ["origami"] = "Origami-crane.jpg|alt=icon", ["osaka"] = "Flag of Osaka City.svg|border|link=|alt=flag", ["osaka university"] = "Toyonaka stone.png|alt=icon", ["oscar wilde"] = "Oscar Wilde, 1882.jpg|link=|alt=", ["ossetian"] = "Idioma osetio.png|border|link=Ossetian language|alt=map", ["ottawa"] = "Flag of Ottawa, Ontario.svg|border|link=|alt=flag", ["ottoman empire"] = "Flag of the Ottoman Empire.svg|border|link=|alt=flag", ["outlines"] = "Global thinking.svg|link=|alt=", ["oxfordshire"] = "EnglandOxfordshire.png|alt=icon", ["oz"] = "Oz flag.svg|alt=icon" } fb254fb478a7be48fd87d03b9e5017a96ddb900c Template:RA 10 139 293 2020-10-16T16:34:12Z Canopus >Jonesey95 0 fix extra space before template when rendered wikitext text/x-wiki {{nowrap|{{#if:{{{1|}}}|{{{1}}}<sup>h</sup>|}} {{#if:{{{2|}}}|{{{2}}}<sup>m</sup>|}} {{#if:{{{3|}}}|{{{3|}}}<sup>s</sup>|}}}}<noinclude> {{documentation}} </noinclude> f457f7f0663d084c3d3296af8b827dc417ce0ac4 Template:OEDsub 10 134 283 2020-11-22T09:35:49Z Canopus >Mathglot 0 "Participating institution" membership required; not "UK public library". Many other institutions, like Athens, most US colleges and universities, and many public libraries in the US provide access. wikitext text/x-wiki {{link note|note={{#ifeq: {{{sentence|no}}} | yes | S | s }}ubscription or [https://www.oed.com/public/login/loggingin#withyourlibrary participating institution membership] required{{#ifeq: {{{sentence|no}}} | yes | . | }}}}<noinclude> {{Documentation}} </noinclude> 66a4cfbe3af90f20ac87af655115d9debd61bb56 Template:Sfn 10 100 215 2021-01-14T23:46:10Z Canopus >Jonesey95 0 add undocumented "ignore-err" (which should be "ignore-error", no?) to error check per a note on my talk page wikitext text/x-wiki <includeonly>{{#invoke:Footnotes|sfn|template=sfn}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using sfn with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Sfn]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | 2 | 3 | 4 | 5 | ignore-err | loc | p | page | pages | postscript | pp | ps | ref | Ref }}<noinclude> {{documentation}} </noinclude> eab6519b2a87e18dc40f39343c71f5848977cc93 Template:Reflist/styles.css 10 88 191 2021-03-08T23:00:26Z Canopus >Izno 0 Changed protection level for "[[Template:Reflist/styles.css]]": match parent ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite)) text text/plain /* {{pp|small=yes}} */ /* can we remove the font size declarations? .references gets a font-size in * common.css that is always 90, and there is nothing else in reflist out in * the wild. May affect column sizes. */ .reflist { font-size: 90%; /* Default font-size */ margin-bottom: 0.5em; list-style-type: decimal; } .reflist .references { font-size: 100%; /* Reset font-size when nested in div.reflist */ margin-bottom: 0; /* Avoid double margin when nested in div.reflist */ list-style-type: inherit; /* Enable custom list style types */ } /* columns-2 and columns-3 are legacy for "2 or more" column view from when the * template was implemented with column-count. */ .reflist-columns-2 { column-width: 30em; } .reflist-columns-3 { column-width: 25em; } /* Reset top margin for lists embedded in columns */ .reflist-columns { margin-top: 0.3em; } .reflist-columns ol { margin-top: 0; } /* Avoid elements breaking between columns */ .reflist-columns li { page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */ break-inside: avoid-column; } .reflist-upper-alpha { list-style-type: upper-alpha; } .reflist-upper-roman { list-style-type: upper-roman; } .reflist-lower-alpha { list-style-type: lower-alpha; } .reflist-lower-greek { list-style-type: lower-greek; } .reflist-lower-roman { list-style-type: lower-roman; } 531a26d48f0e7826c61f764cfb7d5fb200032c34 Module:Math 828 127 269 2021-03-11T22:23:48Z Canopus >Primefac 0 typo fix Scribunto text/plain --[[ This module provides a number of basic mathematical operations. ]] local yesno, getArgs -- lazily initialized local p = {} -- Holds functions to be returned from #invoke, and functions to make available to other Lua modules. local wrap = {} -- Holds wrapper functions that process arguments from #invoke. These act as intemediary between functions meant for #invoke and functions meant for Lua. --[[ Helper functions used to avoid redundant code. ]] local function err(msg) -- Generates wikitext error messages. return mw.ustring.format('<strong class="error">Formatting error: %s</strong>', msg) end local function unpackNumberArgs(args) -- Returns an unpacked list of arguments specified with numerical keys. local ret = {} for k, v in pairs(args) do if type(k) == 'number' then table.insert(ret, v) end end return unpack(ret) end local function makeArgArray(...) -- Makes an array of arguments from a list of arguments that might include nils. local args = {...} -- Table of arguments. It might contain nils or non-number values, so we can't use ipairs. local nums = {} -- Stores the numbers of valid numerical arguments. local ret = {} for k, v in pairs(args) do v = p._cleanNumber(v) if v then nums[#nums + 1] = k args[k] = v end end table.sort(nums) for i, num in ipairs(nums) do ret[#ret + 1] = args[num] end return ret end local function fold(func, ...) -- Use a function on all supplied arguments, and return the result. The function must accept two numbers as parameters, -- and must return a number as an output. This number is then supplied as input to the next function call. local vals = makeArgArray(...) local count = #vals -- The number of valid arguments if count == 0 then return -- Exit if we have no valid args, otherwise removing the first arg would cause an error. nil, 0 end local ret = table.remove(vals, 1) for _, val in ipairs(vals) do ret = func(ret, val) end return ret, count end --[[ Fold arguments by selectively choosing values (func should return when to choose the current "dominant" value). ]] local function binary_fold(func, ...) local value = fold((function(a, b) if func(a, b) then return a else return b end end), ...) return value end --[[ random Generate a random number Usage: {{#invoke: Math | random }} {{#invoke: Math | random | maximum value }} {{#invoke: Math | random | minimum value | maximum value }} ]] function wrap.random(args) local first = p._cleanNumber(args[1]) local second = p._cleanNumber(args[2]) return p._random(first, second) end function p._random(first, second) math.randomseed(mw.site.stats.edits + mw.site.stats.pages + os.time() + math.floor(os.clock() * 1000000000)) -- math.random will throw an error if given an explicit nil parameter, so we need to use if statements to check the params. if first and second then if first <= second then -- math.random doesn't allow the first number to be greater than the second. return math.random(first, second) end elseif first then return math.random(first) else return math.random() end end --[[ order Determine order of magnitude of a number Usage: {{#invoke: Math | order | value }} ]] function wrap.order(args) local input_string = (args[1] or args.x or '0'); local input_number = p._cleanNumber(input_string); if input_number == nil then return err('order of magnitude input appears non-numeric') else return p._order(input_number) end end function p._order(x) if x == 0 then return 0 end return math.floor(math.log10(math.abs(x))) end --[[ precision Detemines the precision of a number using the string representation Usage: {{ #invoke: Math | precision | value }} ]] function wrap.precision(args) local input_string = (args[1] or args.x or '0'); local trap_fraction = args.check_fraction; local input_number; if not yesno then yesno = require('Module:Yesno') end if yesno(trap_fraction, true) then -- Returns true for all input except nil, false, "no", "n", "0" and a few others. See [[Module:Yesno]]. local pos = string.find(input_string, '/', 1, true); if pos ~= nil then if string.find(input_string, '/', pos + 1, true) == nil then local denominator = string.sub(input_string, pos+1, -1); local denom_value = tonumber(denominator); if denom_value ~= nil then return math.log10(denom_value); end end end end input_number, input_string = p._cleanNumber(input_string); if input_string == nil then return err('precision input appears non-numeric') else return p._precision(input_string) end end function p._precision(x) if type(x) == 'number' then x = tostring(x) end x = string.upper(x) local decimal = x:find('%.') local exponent_pos = x:find('E') local result = 0; if exponent_pos ~= nil then local exponent = string.sub(x, exponent_pos + 1) x = string.sub(x, 1, exponent_pos - 1) result = result - tonumber(exponent) end if decimal ~= nil then result = result + string.len(x) - decimal return result end local pos = string.len(x); while x:byte(pos) == string.byte('0') do pos = pos - 1 result = result - 1 if pos <= 0 then return 0 end end return result end --[[ max Finds the maximum argument Usage: {{#invoke:Math| max | value1 | value2 | ... }} Note, any values that do not evaluate to numbers are ignored. ]] function wrap.max(args) return p._max(unpackNumberArgs(args)) end function p._max(...) local max_value = binary_fold((function(a, b) return a > b end), ...) if max_value then return max_value end end --[[ median Find the median of set of numbers Usage: {{#invoke:Math | median | number1 | number2 | ...}} OR {{#invoke:Math | median }} ]] function wrap.median(args) return p._median(unpackNumberArgs(args)) end function p._median(...) local vals = makeArgArray(...) local count = #vals table.sort(vals) if count == 0 then return 0 end if p._mod(count, 2) == 0 then return (vals[count/2] + vals[count/2+1])/2 else return vals[math.ceil(count/2)] end end --[[ min Finds the minimum argument Usage: {{#invoke:Math| min | value1 | value2 | ... }} OR {{#invoke:Math| min }} When used with no arguments, it takes its input from the parent frame. Note, any values that do not evaluate to numbers are ignored. ]] function wrap.min(args) return p._min(unpackNumberArgs(args)) end function p._min(...) local min_value = binary_fold((function(a, b) return a < b end), ...) if min_value then return min_value end end --[[ sum Finds the sum Usage: {{#invoke:Math| sum | value1 | value2 | ... }} OR {{#invoke:Math| sum }} Note, any values that do not evaluate to numbers are ignored. ]] function wrap.sum(args) return p._sum(unpackNumberArgs(args)) end function p._sum(...) local sums, count = fold((function(a, b) return a + b end), ...) if not sums then return 0 else return sums end end --[[ average Finds the average Usage: {{#invoke:Math| average | value1 | value2 | ... }} OR {{#invoke:Math| average }} Note, any values that do not evaluate to numbers are ignored. ]] function wrap.average(args) return p._average(unpackNumberArgs(args)) end function p._average(...) local sum, count = fold((function(a, b) return a + b end), ...) if not sum then return 0 else return sum / count end end --[[ round Rounds a number to specified precision Usage: {{#invoke:Math | round | value | precision }} --]] function wrap.round(args) local value = p._cleanNumber(args[1] or args.value or 0) local precision = p._cleanNumber(args[2] or args.precision or 0) if value == nil or precision == nil then return err('round input appears non-numeric') else return p._round(value, precision) end end function p._round(value, precision) local rescale = math.pow(10, precision or 0); return math.floor(value * rescale + 0.5) / rescale; end --[[ log10 returns the log (base 10) of a number Usage: {{#invoke:Math | log10 | x }} ]] function wrap.log10(args) return math.log10(args[1]) end --[[ mod Implements the modulo operator Usage: {{#invoke:Math | mod | x | y }} --]] function wrap.mod(args) local x = p._cleanNumber(args[1]) local y = p._cleanNumber(args[2]) if not x then return err('first argument to mod appears non-numeric') elseif not y then return err('second argument to mod appears non-numeric') else return p._mod(x, y) end end function p._mod(x, y) local ret = x % y if not (0 <= ret and ret < y) then ret = 0 end return ret end --[[ gcd Calculates the greatest common divisor of multiple numbers Usage: {{#invoke:Math | gcd | value 1 | value 2 | value 3 | ... }} --]] function wrap.gcd(args) return p._gcd(unpackNumberArgs(args)) end function p._gcd(...) local function findGcd(a, b) local r = b local oldr = a while r ~= 0 do local quotient = math.floor(oldr / r) oldr, r = r, oldr - quotient * r end if oldr < 0 then oldr = oldr * -1 end return oldr end local result, count = fold(findGcd, ...) return result end --[[ precision_format Rounds a number to the specified precision and formats according to rules originally used for {{template:Rnd}}. Output is a string. Usage: {{#invoke: Math | precision_format | number | precision }} ]] function wrap.precision_format(args) local value_string = args[1] or 0 local precision = args[2] or 0 return p._precision_format(value_string, precision) end function p._precision_format(value_string, precision) -- For access to Mediawiki built-in formatter. local lang = mw.getContentLanguage(); local value value, value_string = p._cleanNumber(value_string) precision = p._cleanNumber(precision) -- Check for non-numeric input if value == nil or precision == nil then return err('invalid input when rounding') end local current_precision = p._precision(value) local order = p._order(value) -- Due to round-off effects it is neccesary to limit the returned precision under -- some circumstances because the terminal digits will be inaccurately reported. if order + precision >= 14 then if order + p._precision(value_string) >= 14 then precision = 13 - order; end end -- If rounding off, truncate extra digits if precision < current_precision then value = p._round(value, precision) current_precision = p._precision(value) end local formatted_num = lang:formatNum(math.abs(value)) local sign -- Use proper unary minus sign rather than ASCII default if value < 0 then sign = '−' else sign = '' end -- Handle cases requiring scientific notation if string.find(formatted_num, 'E', 1, true) ~= nil or math.abs(order) >= 9 then value = value * math.pow(10, -order) current_precision = current_precision + order precision = precision + order formatted_num = lang:formatNum(math.abs(value)) else order = 0; end formatted_num = sign .. formatted_num -- Pad with zeros, if needed if current_precision < precision then local padding if current_precision <= 0 then if precision > 0 then local zero_sep = lang:formatNum(1.1) formatted_num = formatted_num .. zero_sep:sub(2,2) padding = precision if padding > 20 then padding = 20 end formatted_num = formatted_num .. string.rep('0', padding) end else padding = precision - current_precision if padding > 20 then padding = 20 end formatted_num = formatted_num .. string.rep('0', padding) end end -- Add exponential notation, if necessary. if order ~= 0 then -- Use proper unary minus sign rather than ASCII default if order < 0 then order = '−' .. lang:formatNum(math.abs(order)) else order = lang:formatNum(order) end formatted_num = formatted_num .. '<span style="margin:0 .15em 0 .25em">×</span>10<sup>' .. order .. '</sup>' end return formatted_num end --[[ divide Implements the division operator Usage: {{#invoke:Math | divide | x | y | round= | precision= }} --]] function wrap.divide(args) local x = args[1] local y = args[2] local round = args.round local precision = args.precision if not yesno then yesno = require('Module:Yesno') end return p._divide(x, y, yesno(round), precision) end function p._divide(x, y, round, precision) if y == nil or y == "" then return err("Empty divisor") elseif not tonumber(y) then if type(y) == 'string' and string.sub(y, 1, 1) == '<' then return y else return err("Not a number: " .. y) end elseif x == nil or x == "" then return err("Empty dividend") elseif not tonumber(x) then if type(x) == 'string' and string.sub(x, 1, 1) == '<' then return x else return err("Not a number: " .. x) end else local z = x / y if round then return p._round(z, 0) elseif precision then return p._round(z, precision) else return z end end end --[[ Helper function that interprets the input numerically. If the input does not appear to be a number, attempts evaluating it as a parser functions expression. ]] function p._cleanNumber(number_string) if type(number_string) == 'number' then -- We were passed a number, so we don't need to do any processing. return number_string, tostring(number_string) elseif type(number_string) ~= 'string' or not number_string:find('%S') then -- We were passed a non-string or a blank string, so exit. return nil, nil; end -- Attempt basic conversion local number = tonumber(number_string) -- If failed, attempt to evaluate input as an expression if number == nil then local success, result = pcall(mw.ext.ParserFunctions.expr, number_string) if success then number = tonumber(result) number_string = tostring(number) else number = nil number_string = nil end else number_string = number_string:match("^%s*(.-)%s*$") -- String is valid but may contain padding, clean it. number_string = number_string:match("^%+(.*)$") or number_string -- Trim any leading + signs. if number_string:find('^%-?0[xX]') then -- Number is using 0xnnn notation to indicate base 16; use the number that Lua detected instead. number_string = tostring(number) end end return number, number_string end --[[ Wrapper function that does basic argument processing. This ensures that all functions from #invoke can use either the current frame or the parent frame, and it also trims whitespace for all arguments and removes blank arguments. ]] local mt = { __index = function(t, k) return function(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end return wrap[k](getArgs(frame)) -- Argument processing is left to Module:Arguments. Whitespace is trimmed and blank arguments are removed. end end } return setmetatable(p, mt) 2bbe734d898299f65412963a3c1782e9fcc4d9ca Module:Template wrapper 828 125 265 2021-05-08T08:01:01Z Canopus >GKFX 0 Add uncopyable line break opportunities to documentation mode Scribunto text/plain require('Module:No globals'); local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; --[[--------------------------< I S _ I N _ T A B L E >-------------------------------------------------------- scan through tbl looking for value; return true if found, false else ]] local function is_in_table (tbl, value) for k, v in pairs (tbl) do if v == value then return true end end return false; end --[[--------------------------< A D D _ P A R A M E T E R >---------------------------------------------------- adds parameter name and its value to args table according to the state of boolean list argument; kv pair for template execution; k=v string for template listing. ]] local function add_parameter (k, v, args, list) if list then table.insert( args, table.concat ({k, '=', v})); -- write parameter names and values to args table as string else args[k] = v; -- copy parameters to args table end end --[[--------------------------< A L I A S _ M A P _ G E T >---------------------------------------------------- returns a table of local template (parent frame) parameter names and the target template names that match where in [key]=<value> pairs where: [key] is local template parameter name (an alias) <value> is target template parameter name (the canonical parameter name used in the working template) The parameter |_alias-map= has the form: |_alias-map=<list> where <list> is a comma-separated list of alias / canonical parameter name pairs in the form <from> : <to> where: <from> is the local template's parameter name (alias) <to> is the target template's parameter name (canonical) for enumerated parameters place an octothorp (#) where the enumerator digits are placed in the parameter names: <from#> : <to#> ]] local function alias_map_get (_alias_map) local T = mw.text.split (_alias_map, '%s*,%s*'); -- convert the comma-separated list into a table of alias pairs local mapped_aliases = {}; -- mapped aliases will go here local l_name, t_name; -- parameter names for _, alias_pair in ipairs (T) do -- loop through the table of alias pairs l_name, t_name = alias_pair:match ('(.-)%s*:%s*(.+)'); -- from each pair, get local and target parameter names if l_name and t_name then -- if both are set if tonumber (l_name) then l_name = tonumber (l_name); -- convert number-as-text to a number end mapped_aliases[l_name] = t_name; -- add them to the map table end end return mapped_aliases; end --[[--------------------------< F R A M E _ A R G S _ G E T >-------------------------------------------------- Fetch the wrapper template's 'default' and control parameters; adds default parameters to args returns content of |_template= parameter (name of the working template); nil else ]] local function frame_args_get (frame_args, args, list) local template; for k, v in pairs (frame_args) do -- here we get the wrapper template's 'default' parameters if 'string' == type (k) and (v and ('' ~= v)) then -- do not pass along positional or empty parameters if '_template' == k then template = v; -- save the name of template that we are wrapping elseif '_exclude' ~= k and '_reuse' ~= k and '_include-positional' ~= k and '_alias-map' ~= k then -- these already handled so ignore here; add_parameter (k, v, args, list); -- add all other parameters to args in the style dictated by list end end end return template; -- return contents of |_template= parameter end --[=[--------------------------< P F R A M E _ A R G S _ G E T >------------------------------------------------ Fetches the wrapper template's 'live' parameters; adds live parameters that aren't members of the exclude table to args table; positional parameters may not be excluded no return value ]=] local function pframe_args_get (pframe_args, args, exclude, _include_positional, list) for k, v in pairs (pframe_args) do if 'string' == type (k) and not is_in_table (exclude, k) then -- do not pass along excluded parameters if v and ('' ~= v) then -- pass along only those parameters that have assigned values if 'unset' == v:lower() then -- special keyword to unset 'default' parameters set in the wrapper template v = ''; -- unset the value in the args table end add_parameter (k, v, args, list) -- add all other parameters to args in the style dictated by list; alias map only supported for local-template parameters end end end if _include_positional then for i, v in ipairs (pframe_args) do -- pass along positional parameters if 'unset' == v:lower() then -- special keyword to unset 'default' parameters set in the wrapper template v = ''; -- unset the value in the args table end add_parameter (i, v, args, list); end end end --[[--------------------------< _ M A I N >-------------------------------------------------------------------- Collect the various default and live parameters into args styled according to boolean list. returns name of the working or listed template or nil for an error message ]] local function _main (frame, args, list) local template; local exclude = {}; -- table of parameter names for parameters that are not passed to the working template local reuse_list = {}; -- table of pframe parameter names whose values are modified before they are passed to the working template as the same name local alias_map = {}; -- table that maps parameter aliases to working template canonical parameter names local _include_positional; if frame.args._exclude and ('' ~= frame.args._exclude) then -- if there is |_exclude= and it's not empty exclude = mw.text.split (frame.args._exclude, "%s*,%s*"); -- make a table from its contents end -- TODO: |_reuse= needs a better name (|_reuse=) if frame.args._reuse and ('' ~= frame.args._reuse) then -- if there is |_reuse= and it's not empty reuse_list = mw.text.split (frame.args._reuse, "%s*,%s*"); -- make a table from its contents end if frame.args['_alias-map'] and ('' ~= frame.args['_alias-map']) then -- if there is |_alias-map= and it's not empty alias_map = alias_map_get (frame.args['_alias-map']); -- make a table from its contents end template = frame_args_get (frame.args, args, list); -- get parameters provided in the {{#invoke:template wrapper|...|...}} if nil == template or '' == template then -- this is the one parameter that is required by this module return nil; -- not present, tell calling function to emit an error message end _include_positional = 'yes' == frame.args['_include-positional']; -- when true pass all positional parameters along with non-excluded named parameters to ... -- ... the working template; positional parameters are not excludable local _pframe_args = frame:getParent().args; -- here we get the wrapper template's 'live' parameters from pframe.args local pframe_args = {}; -- a local table that we can modify for k, v in pairs (_pframe_args) do -- make a copy that we can modify pframe_args[k] = v; end -- here we look for pframe parameters that are aliases of canonical parameter names; when found -- we replace the alias with the canonical. We do this here because the reuse_list works on -- canonical parameter names so first we convert alias parameter names to canonical names and then -- we remove those canonical names from the pframe table that are reused (provided to the working -- template through the frame args table) for k, v in pairs (alias_map) do -- k is alias name, v is canonical name if pframe_args[k] then -- if pframe_args has parameter with alias name pframe_args[v] = _pframe_args[k]; -- create new canonical name with alias' value pframe_args[k] = nil; -- unset the alias end end for k, v in pairs (pframe_args) do -- do enumerated parameter alias -> canonical translation if 'string' == type (k) then -- only named parameters can be enumerated if alias_map[k..'#'] then -- non-enumerated alias matches enumerated parameter pattern? enumerator at end only pframe_args[alias_map[k..'#']:gsub('#', '')] = v; -- remove '#' and copy parameter to pframe_args table pframe_args[k] = nil; -- unset the alias elseif k:match ('%d+') then -- if this parameter name contains digits local temp = k:gsub ('%d+', '#'); -- make a copy; digits replaced with single '#' local enum = k:match ('%d+'); -- get the enumerator if alias_map[temp] then -- if this parameter is a recognized enumerated alias pframe_args[alias_map[temp]:gsub('#', enum)] = v; -- use canonical name and replace '#' with enumerator and add to pframe_args pframe_args[k] = nil; -- unset the alias end end end end -- pframe parameters that are _reused are 'reused' have the form something like this: -- |chapter=[[wikisource:{{{chapter}}}|{{{chapter}}}]] -- where a parameter in the wrapping template is modified and then passed to the working template -- using the same parameter name (in this example |chapter=) -- remove parameters that will be reused for k, v in ipairs (reuse_list) do -- k is numerical index, v is canonical parameter name to ignore if pframe_args[v] then -- if pframe_args has parameter that should be ignored pframe_args[v] = nil; -- unset the ignored parameter end end pframe_args_get (pframe_args, args, exclude, _include_positional, list); -- add parameters and values to args that are not listed in the exclude table return template; -- args now has all default and live parameters, return working template name end --[[--------------------------< W R A P >---------------------------------------------------------------------- Template entry point. Call this function to 'execute' the working template ]] local function wrap (frame) local args = {}; -- table of default and live parameters and their values to be passed to the wrapped template local template; -- the name of the working template template = _main (frame, args, false); -- get default and live parameters and the name of the working template if not template then -- template name is required return error_msg; -- emit error message and abandon if template name not present end return frame:expandTemplate {title=template, args=args}; -- render the working template end --[[--------------------------< L I S T >---------------------------------------------------------------------- Template entry point. Call this function to 'display' the source for the working template. This function added as a result of a TfD here: Wikipedia:Templates_for_discussion/Log/2018_April_28#Module:PassArguments This function replaces a similarly named function which was used in {{cite compare}} and {{cite compare2}} Values in the args table are numerically indexed strings in the form 'name=value' ]] local function list(frame, do_link) local args = {}; -- table of default and live parameters and their values to be passed to the listed template local template; -- the name of the listed template template = _main (frame, args, true); -- get default and live parameters and the name of the listed template if not template then -- template name is required return error_msg; -- emit error message and abandon if template name not present end if do_link then template = ('[[%s|%s]]'):format(frame:expandTemplate{ title='Transclude', args = {template} }, template) end table.sort(args) for i = 1, #args do local stripped = args[i]:match('^' .. i .. '=([^=]*)$') if stripped then args[i] = stripped else break end end return frame:preprocess(table.concat({ '<code style="color:inherit; background:inherit; border:none;">&#123;&#123;', template, ('<wbr><nowiki>|%s</nowiki>'):rep(#args):format(unpack(args)), '&#125;&#125;</code>'})); -- render the template end local function link (frame) return list(frame, true) end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { link = link, list = list, wrap = wrap, }; aa1b56cac4081642637ea7d11fba53513d4335a7 Template:Trim 10 120 255 2021-06-13T14:06:25Z Canopus >Plastikspork 0 Fix for |=foo bug wikitext text/x-wiki <includeonly>{{safesubst:#if:1|{{{x|{{{1|}}}}}}}}</includeonly><noinclude> {{Documentation}} </noinclude> 09ba1a40d9fd41a44a407b144f69a579502fe563 Template:Navbox 10 98 211 2021-06-26T18:05:09Z Canopus >Trialpears 0 Remove TfD notice as it wouldn't involve any changes to this template. wikitext text/x-wiki <includeonly>{{#invoke:Navbox|navbox}}</includeonly><noinclude> {{Documentation}} </noinclude> fe9b964401f895918ee4fe078678f1722a3c41ec Template:Sclass 10 128 271 2021-07-02T16:02:05Z Canopus >Trappist the monk 0 format name change; wikitext text/x-wiki <includeonly>{{sclass/core|1={{{1}}}|2={{{2}}}|3={{{3|}}}|4={{{4|}}}|5={{{5|}}}|format=sclass}}</includeonly><!-- --><noinclude>{{documentation}}</noinclude> 9e6cac27c57200a375f9fd66187d590a922157d2 Template:Starbox catalog 10 154 323 2021-07-09T10:05:40Z Canopus >Primefac 0 rmv interwikis wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><th style="background-color: #FFFFC0; text-align: center;" colspan="2">[[Star catalogue|Other designations]]</th></tr><!-- --><tr><td colspan="2"><div style="width: 250px;"> {{{names<includeonly>|</includeonly>}}} </div></td></tr><!-- -->{{#if:{{{component1<includeonly>|</includeonly>}}}|<tr><td colspan="2">'''{{{component1}}}''': {{{names1}}}</td></tr>}}<!-- -->{{#if:{{{component2<includeonly>|</includeonly>}}}|<tr><td colspan="2">'''{{{component2}}}''': {{{names2}}}</td></tr>}}<!-- -->{{#if:{{{component3<includeonly>|</includeonly>}}}|<tr><td colspan="2">'''{{{component3}}}''': {{{names3}}}</td></tr>}}<!-- -->{{#if:{{{component4<includeonly>|</includeonly>}}}|<tr><td colspan="2">'''{{{component4}}}''': {{{names4}}}</td></tr>}}<noinclude> |} {{Documentation}} </noinclude> 5a833fd635cee397f343a44ca1cb8ea26ae44be3 Module:Pagetype/config 828 60 135 2021-07-10T15:47:32Z Canopus >Trialpears 0 Book namespace removal will happen within a few days Scribunto text/plain -------------------------------------------------------------------------------- -- Module:Pagetype configuration data -- -- This page holds localisation and configuration data for Module:Pagetype. -- -------------------------------------------------------------------------------- local cfg = {} -- Don't edit this line. -------------------------------------------------------------------------------- -- Start configuration data -- -------------------------------------------------------------------------------- -- This table holds the values to use for "main=true", "user=true", etc. Keys to -- this table should be namespace parameters that can be used with -- [[Module:Namespace detect]]. cfg.pagetypes = { ['main'] = 'article', ['user'] = 'user page', ['project'] = 'project page', ['wikipedia'] = 'project page', ['wp'] = 'project page', ['file'] = 'file', ['image'] = 'file', ['mediawiki'] = 'interface page', ['template'] = 'template', ['help'] = 'help page', ['category'] = 'category', ['portal'] = 'portal', ['draft'] = 'draft', ['timedtext'] = 'Timed Text page', ['module'] = 'module', ['topic'] = 'topic', ['gadget'] = 'gadget', ['gadget definition'] = 'gadget definition', ['talk'] = 'talk page', ['special'] = 'special page', ['media'] = 'file', } -- This table holds the names of the namespaces to be looked up from -- cfg.pagetypes by default. cfg.defaultNamespaces = { 'main', 'file', 'template', 'category', 'module' } -- This table holds the names of the namespaces to be looked up from -- cfg.pagetypes if cfg.defaultnsExtended is set. cfg.extendedNamespaces = { 'main', 'user', 'project', 'file', 'mediawiki', 'template', 'category', 'help', 'portal', 'module', 'draft' } -- The parameter name to set which default namespace values to be looked up from -- cfg.pagetypes. cfg.defaultns = 'defaultns' -- The value of cfg.defaultns to set all namespaces, including talk. cfg.defaultnsAll = 'all' -- The value of cfg.defaultns to set the namespaces listed in -- cfg.extendedNamespaces cfg.defaultnsExtended = 'extended' -- The value of cfg.defaultns to set no default namespaces. cfg.defaultnsNone = 'none' -- The parameter name to use for disambiguation pages page. cfg.dab = 'dab' -- This table holds the different possible aliases for disambiguation-class -- pages. These should be lower-case. cfg.dabAliases = { 'disambiguation', 'disambig', 'disamb', 'dab' } -- The default value for disambiguation pages. cfg.dabDefault = 'page' -- The parameter name to use for N/A-class page. cfg.na = 'na' -- This table holds the different possible aliases for N/A-class pages. These -- should be lower-case. cfg.naAliases = {'na', 'n/a'} -- The default value for N/A-class pages. cfg.naDefault = 'page' -- The parameter name to use for redirects. cfg.redirect = 'redirect' -- The default value to use for redirects. cfg.redirectDefault = 'redirect' -- The parameter name for undefined namespaces. cfg.other = 'other' -- The value used if the module detects an undefined namespace. cfg.otherDefault = 'page' -- The usual suffix denoting a plural. cfg.plural = 's' -- This table holds plurals not formed by a simple suffix. cfg.irregularPlurals = { ["category"] = "categories" } -------------------------------------------------------------------------------- -- End configuration data -- -------------------------------------------------------------------------------- return cfg -- Don't edit this line e2eb36d6c43611a422bae37947ebeb04b695dcba Module:Hatnote/styles.css 828 108 231 2021-07-12T19:22:27Z Canopus >Izno 0 per my talk page text text/plain /* {{pp|small=y}} */ .hatnote { font-style: italic; } /* Limit structure CSS to divs because of [[Module:Hatnote inline]] */ div.hatnote { /* @noflip */ padding-left: 1.6em; margin-bottom: 0.5em; } .hatnote i { font-style: normal; } /* The templatestyles element inserts a link element before hatnotes. * TODO: Remove link if/when WMF resolves T200206 */ .hatnote + link + .hatnote { margin-top: -0.5em; } 44680ffd6e888866df2cdfa0341af9c7b97da94c Module:Footnotes 828 102 219 2021-09-14T12:03:42Z Canopus >Trappist the monk 0 Scribunto text/plain require('Module:No globals'); local getArgs = require ('Module:Arguments').getArgs; --[[--------------------------< A R G S _ D E F A U L T >------------------------------------------------------ a table to specify initial values. ]] local args_default = { bracket_left = '', bracket_right = '', bracket_year_left = '', bracket_year_right = '', postscript = '', page = '', pages = '', location = '', page_sep = ", p.&nbsp;", pages_sep = ", pp.&nbsp;", ref = '', template = 'harv', -- if template name not provided in {{#invoke:}} use this }; --[[--------------------------< T A R G E T _ C H E C K >------------------------------------------------------ look for anchor_id (CITEREF name-list and year or text from |ref=) in anchor_id_list the 'no target' error may be suppressed with |ignore-err=yes when target cannot be found because target is inside a template that wraps another template; 'multiple targets' error may not be suppressed ]] local function target_check (anchor_id, args) local namespace = mw.title.getCurrentTitle().namespace; local anchor_id_list_module = mw.loadData ('Module:Footnotes/anchor_id_list'); local anchor_id_list = anchor_id_list_module.anchor_id_list; local article_whitelist = anchor_id_list_module.article_whitelist; local template_list = anchor_id_list_module.template_list; local whitelist_module = mw.loadData ('Module:Footnotes/whitelist'); local whitelist = whitelist_module.whitelist; local special_patterns = whitelist_module.special_patterns; local DNB_special_patterns = whitelist_module.DNB_special_patterns; local DNB_template_names = whitelist_module.DNB_template_names; if 10 == namespace then return ''; -- automatic form of |no-tracking=yes; TODO: is this too broad? end local tally = anchor_id_list[anchor_id]; -- nil when anchor_id not in list; else a tally local msg; local category; if not tally then if args.ignore then return ''; -- if ignore is true then no message, no category end if article_whitelist and article_whitelist[anchor_id] then -- if an article-local whitelist and anchor ID is in it return ''; -- done end local wl_anchor_id = anchor_id; -- copy to be modified to index into the whitelist if args.year then -- for anchor IDs created by this template (not in |ref=) that have a date if args.year:match ('%d%l$') or -- use the date value to determine if we should remove the disambiguator args.year:match ('n%.d%.%l$') or args.year:match ('nd%l$') then wl_anchor_id = wl_anchor_id:gsub ('%l$', ''); -- remove the disambiguator end end local t_tbl = whitelist[wl_anchor_id]; -- get list of templates associated with this anchor ID if t_tbl then -- when anchor ID not whitelisted t_tbl is nil for _, t in ipairs (t_tbl) do -- spin through the list of templates associated with this anchor ID if template_list[t] then -- if associated template is found in the list of templates in the article return ''; -- anchor ID is whitlisted and article has matching template so no error end end end for _, pattern in ipairs (special_patterns) do -- spin through the spcial patterns and try to match if anchor_id:match (pattern) then return ''; end end for _, dnb_t in ipairs (DNB_template_names or {}) do -- getting desparate now, are there any DNB templates? DNB_template_names may be nil; empty table prevents script error if template_list[dnb_t] then -- if the article has this DNB template for _, pattern in ipairs (DNB_special_patterns) do -- spin through the DNB-specifiec wildcard patterns if anchor_id:match (pattern) then -- and attempt a match return ''; -- found a match end end end end msg = 'no target: ' .. anchor_id; -- anchor_id not found category = '[[Category:Harv and Sfn no-target errors]]'; elseif 1 < tally then msg = 'multiple targets (' .. tally .. '×): ' .. anchor_id; -- more than one anchor_id in this article category = 0 == namespace and '[[Category:Harv and Sfn multiple-target errors]]' or ''; -- only categorize in article space return '<span class="error harv-error" style="display: inline; font-size:100%"> ' .. args.template .. ' error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category; end -- category = 0 == namespace and '[[Category:Harv and Sfn template errors]]' or ''; -- only categorize in article space category = 0 == namespace and category or ''; -- only categorize in article space --use this version to show error messages -- return msg and '<span class="error harv-error" style="display: inline; font-size:100%"> ' .. args.template .. ' error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category or ''; --use this version to hide error messages return msg and '<span class="error harv-error" style="display: none; font-size:100%"> ' .. args.template .. ' error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category or ''; end --[[--------------------------< I S _ Y E A R >---------------------------------------------------------------- evaluates param to see if it is one of these forms with or without lowercase letter disambiguator: YYYY n.d. nd c. YYYY YYYY–YYYY (separator is endash) YYYY–YY (separator is endash) return true when param has a recognized form; false else ]] local patterns_date= { '^%d%d%d%d?%l?$', '^n%.d%.%l?$', '^nd%l?$', '^c%. %d%d%d%d?%l?$', '^%d%d%d%d–%d%d%d%d%l?$', '^%d%d%d%d–%d%d%l?$', } local function is_year (param, args) args.year = ''; -- used for harv error; for _, pattern in ipairs (patterns_date) do if mw.ustring.match (param, pattern) then args.year = param; -- used for harv error; return true; end end end --[[--------------------------< C O R E >---------------------------------------------------------------------- returns an anchor link (CITEREF) formed from one to four author names, year, and insource location (|p=, |pp=, loc=) ]] local function core( args ) local result; local err_msg = '' if args.P5 ~= '' then if is_year (args.P5, args) then result = table.concat ({args.P1, ' et al. ', args.bracket_year_left, args.P5, args.bracket_year_right}); else args.P5 = ''; -- when P5 not a year don't include in anchor result = table.concat ({args.P1, ' et al.'}); -- and don't render it end elseif args.P4 ~= '' then if is_year (args.P4, args) then result = table.concat ({args.P1, ', ', args.P2, ' &amp; ', args.P3, ' ', args.bracket_year_left, args.P4, args.bracket_year_right}); -- three names and a year else result = table.concat ({args.P1, ' et al.'}); -- four names end elseif args.P3 ~= '' then if is_year (args.P3, args) then result = table.concat ({args.P1, ' &amp; ', args.P2, ' ', args.bracket_year_left, args.P3, args.bracket_year_right}); -- two names and a year else result = table.concat ({args.P1, ', ', args.P2, ' ', ' &amp; ', args.P3}); -- three names end elseif args.P2 ~= '' then if is_year (args.P2, args) then result = table.concat ({args.P1, ' ', args.bracket_year_left, args.P2, args.bracket_year_right}); -- one name and year else result = table.concat ({args.P1, ' &amp; ', args.P2}); -- two names end else result = args.P1; -- one name end -- when author-date result ends with a dot (typically when the last positional parameter holds 'n.d.') -- and when no in-source location (no |p=, |pp=, or |loc=) -- and when the first or only character in args.postscript is a dot -- remove the author-date result trailing dot -- the author-date result trailing dot will be replaced later with the content of args.postscript (usually a dot) if ('.' == result:sub(-1)) and ('.' == args.postscript:sub(1)) and ('' == args.page) and ('' == args.pages) and ('' == args.location) then result = result:gsub ('%.$', ''); end if args.ref ~= 'none' then local anchor_id; if args.ref ~= '' then anchor_id = mw.uri.anchorEncode (args.ref); err_msg = target_check (anchor_id, args); result = table.concat ({'[[#', anchor_id, '|', result, ']]'}); else anchor_id = mw.uri.anchorEncode (table.concat ({'CITEREF', args.P1, args.P2, args.P3, args.P4, args.P5})); err_msg = target_check (anchor_id, args); result = table.concat ({'[[#', anchor_id, '|', result, ']]'}); end end if args.page ~= '' then result = table.concat ({result, args.page_sep, args.page}); elseif args.pages ~= ''then result = table.concat ({result, args.pages_sep, args.pages}); end if args.location ~= '' then result = table.concat ({result, ', ', args.location}); end result = table.concat ({args.bracket_left, result, args.bracket_right, args.postscript}):gsub ('%s+', ' '); -- strip redundant spaces return result .. err_msg; end --[[--------------------------< H Y P H E N _ T O _ D A S H >-------------------------------------------------- Converts a hyphen to a dash under certain conditions. The hyphen must separate like items; unlike items are returned unmodified. These forms are modified: letter - letter (A - B) digit - digit (4-5) digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5) letterdigit - letterdigit (A1-A5) (an optional separator between letter and digit is supported – a.1-a.5 or a-1-a-5) digitletter - digitletter (5a - 5d) (an optional separator between letter and digit is supported – 5.a-5.d or 5-a-5-d) any other forms are returned unmodified. str may be a comma- or semicolon-separated list This code copied from Module:Citation/CS1. The only modification is to require Module:Citation/CS1/Utilities so that it has access to the functions is_set() and has_accept_as_written() ]] local function hyphen_to_dash( str ) local utilities = require ('Module:Citation/CS1/Utilities'); -- only modification so that this function has access to is_set() and has_accept_as_written() if not utilities.is_set (str) then return str; end local accept; -- Boolean str = str:gsub ('&[nm]dash;', {['&ndash;'] = '–', ['&mdash;'] = '—'}); -- replace &mdash; and &ndash; entities with their characters; semicolon mucks up the text.split str = str:gsub ('&#45;', '-'); -- replace HTML numeric entity with hyphen character str = str:gsub ('&nbsp;', ' '); -- replace &nbsp; entity with generic keyboard space character local out = {}; local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any for _, item in ipairs (list) do -- for each item in the list item, accept = utilities.has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators if item:match ('^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$') or -- letterdigit hyphen letterdigit (optional separator between letter and digit) item:match ('^%d+[%.%-]?%a+%s*%-%s*%d+[%.%-]?%a+$') or -- digitletter hyphen digitletter (optional separator between digit and letter) item:match ('^%d+[%.%-]%d+%s*%-%s*%d+[%.%-]%d+$') or -- digit separator digit hyphen digit separator digit item:match ('^%d+%s*%-%s*%d+$') or -- digit hyphen digit item:match ('^%a+%s*%-%s*%a+$') then -- letter hyphen letter item = item:gsub ('(%w*[%.%-]?%w+)%s*%-%s*(%w*[%.%-]?%w+)', '%1–%2'); -- replace hyphen, remove extraneous space characters else item = mw.ustring.gsub (item, '%s*[–—]%s*', '–'); -- for endash or emdash separated ranges, replace em with en, remove extraneous whitespace end end table.insert (out, item); -- add the (possibly modified) item to the output table end local temp_str = ''; -- concatenate the output table into a comma separated string temp_str, accept = utilities.has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out if accept then temp_str = utilities.has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value return temp_str; else return temp_str; -- else, return assembled temp_str end end --[[--------------------------< A R G S _ F E T C H >--------------------------------------------------------- Because all of the templates share a common set of parameters, a single common function to fetch those parameters from frame and parent frame. ]] local function args_fetch (frame, ps) local args = args_default; -- create a copy of the default table local pframe = frame:getParent(); -- point to the template's parameter table for k, v in pairs (frame.args) do -- override defaults with values provided in the #invoke: if any args[k] = v; end args.postscript = pframe.args.postscript or pframe.args.ps or ps; if 'none' == args.postscript then args.postscript = ''; end args.page = pframe.args.p or pframe.args.page or ''; args.pages = pframe.args.pp or pframe.args.pages or ''; args.pages = ('' ~= args.pages) and hyphen_to_dash (args.pages) or ''; args.location = pframe.args.loc or ''; args.ref = pframe.args.ref or pframe.args.Ref or ''; args.ignore = ('yes' == pframe.args['ignore-false-positive']) or ('yes' == pframe.args['ignore-err']); for i, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- loop through the five positional parameters and trim if set else empty string args[v] = (pframe.args[i] and mw.text.trim (pframe.args[i])) or ''; end if args.P5 and not is_year (args.P5, args) then local i = 6; -- initialize the indexer to the sixth positional parameter while pframe.args[i] do -- in case there are too many authors loop through the authors looking for a year local v = mw.text.trim (pframe.args[i]); -- trim if is_year (v, args) then -- if a year args.P5 = v; -- overwrite whatever was in args.P5 with year break; -- and abandon the search end i = i + 1; -- bump the indexer end end return args; end --[[--------------------------< H A R V A R D _ C I T A T I O N >---------------------------------------------- common entry point for: {{harvard citation}} aka {{harv}} {{Harvard citation no brackets}} aka {{harvnb}} {{harvcol}} {{harvcolnb}} {{harvcoltxt}} {{Harvard citation text}} aka {{harvtxt}} {{Harvp}} Distinguishing features (brackets and page separators) are specified in this module's {{#invoke}} in the respective templates. ]] local function harvard_citation (frame) local args = args_fetch (frame, ''); -- get the template and invoke parameters; default postscript is empty string return core (args); end --[[--------------------------< S T R I P _ U R L >------------------------------------------------------------ used by sfn() and sfnm(). This function fixes an issue with reference tooltip gadget where the tooltip is not displayed when an insource locator (|p=, |pp=, |loc=) has an external wikilink that contains a # character strip uri-reserved characters from urls in |p=, |pp-, and |loc= parameters The researved characters are: !#$&'()*+,/:;=?@[] ]] local function strip_url (pages) local escaped_uri; if not pages or ('' == pages) then return pages; end for uri in pages:gmatch ('%[(%a[%w%+%.%-]*://%S+)') do -- for each external link get the uri escaped_uri = uri:gsub ("([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ); -- save a copy with lua pattern characters escaped uri = uri:gsub ("[!#%$&'%(%)%*%+,/:;=%?@%[%]%.%%]", ''); -- remove reserved characters and '%' because '%20' (space character) is a lua 'invalid capture index' pages = pages:gsub (escaped_uri, uri, 1); -- replace original uri with the stripped version end return pages; end --[[--------------------------< S F N >------------------------------------------------------------------------ entry point for {{sfn}} and {{sfnp}} ]] local function sfn (frame) local args = args_fetch (frame, '.'); -- get the template and invoke parameters; default postscript is a dot local result = core (args); -- go make a CITEREF anchor -- put it all together and then strip redundant spaces local name = table.concat ({'FOOTNOTE', args.P1, args.P2, args.P3, args.P4, args.P5, strip_url (args.page), strip_url (args.pages), strip_url (args.location)}):gsub ('%s+', ' '); return frame:extensionTag ({name='ref', args={name=name}, content=result}); end --[[--------------------------< S F N M >---------------------------------------------------------------------- common entry point for {{sfnm}} and {{sfnmp}} Distinguishing features (brackets) are specified in this module's {{#invoke}} in the respective templates. ]] local function sfnm (frame) local args = args_default; -- create a copy of the default table local pframe = frame:getParent(); -- point to the template's parameter table local n = 1; -- index of source; this is the 'n' in na1, ny, etc local first_pnum = 1; -- first of a pair of positional parameters local second_pnum = 2; -- second of a pair of positional parameters local last_ps = 0; -- index of the last source with |nps= set local last_index = 0; -- index of the last source; these used to determine which of |ps= or |nps= will terminate the whole rendering local out = {}; -- table to hold rendered sources local footnote = {'FOOTNOTE'}; -- all author, date, insource location stuff becomes part of the reference's footnote id; added as we go for k, v in pairs (frame.args) do -- override defaults with values provided in the #invoke: if any args[k] = v; end while true do if not pframe.args[table.concat ({n, 'a1'})] and not pframe.args[first_pnum] then break; -- no na1 or matching positional parameter so done end if pframe.args[table.concat ({n, 'a1'})] then -- does this source use named parameters? for _, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- initialize for this source args[v] = ''; end for i, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- extract author and year parameters for this source args[v] = pframe.args[table.concat ({n, 'a', i})] or ''; -- attempt to assign author name if '' == args[v] then -- when there wasn't an author name args[v] = pframe.args[table.concat ({n, 'y'})] or ''; -- attempt to assign year break; -- done with author/date for this source end end else -- this source uses positional parameters args.P1 = mw.text.trim (pframe.args[first_pnum]); -- yes, only one author supported args.P2 = (pframe.args[second_pnum] and mw.text.trim (pframe.args[second_pnum])) or ''; -- when positional author, year must also be positional for _, v in ipairs ({'P3', 'P4', 'P5'}) do -- blank the rest of these for this source args[v] = ''; end first_pnum = first_pnum + 2; -- source must use positional author and positional year second_pnum = first_pnum + 1; -- bump these for possible next positional source end args.postscript = pframe.args[table.concat ({n, 'ps'})] or ''; if 'none' == args.postscript then -- this for compatibility with other footnote templates; does nothing args.postscript = ''; end args.ref = pframe.args[table.concat ({n, 'ref'})] or ''; -- alternate reference for this source args.page = pframe.args[table.concat ({n, 'p'})] or ''; -- insource locations for this source args.pages = pframe.args[table.concat ({n, 'pp'})] or ''; args.pages = ('' ~= args.pages) and hyphen_to_dash (args.pages) or ''; args.location = pframe.args[table.concat ({n, 'loc'})] or ''; args.ignore = ('yes' == pframe.args[table.concat ({n, 'ignore-false-positive'})]) or ('yes' == pframe.args[table.concat ({n, 'ignore-err'})]); table.insert (out, core (args)); -- save the rendering of this source for k, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- create the FOOTNOTE id if '' ~= args[v] then table.insert (footnote, args[v]); end end for k, v in ipairs ({'page', 'pages', 'location'}) do -- these done separately so that we can strip uri-reserved characters from extlinked page numbers if '' ~= args[v] then table.insert (footnote, strip_url (args[v])) end end last_index = n; -- flags used to select terminal postscript from nps or from end_ps if '' ~= args.postscript then last_ps = n; end n = n+1; -- bump for the next one end local name = table.concat (footnote):gsub ('%s+', ' '); -- put the footnote together and strip redundant space args.end_ps = pframe.args.postscript or pframe.args.ps or '.'; -- this is the postscript for the whole not for the individual sources if 'none' == args.end_ps then -- not an original sfnm parameter value; added for compatibility with other footnote templates args.end_ps = ''; end local result = table.concat ({table.concat (out, '; '), (last_index == last_ps) and '' or args.end_ps}); return frame:extensionTag ({name='ref', args={name=name}, content=result}); end --[[--------------------------< S F N R E F >------------------------------------------------------------------ implements {{sfnref}} ]] local function sfnref (frame) local args = getArgs (frame); local out = {}; for i=1, 5 do -- get the first five args if there are five args if args[i] then out[i] = args[i]; else break; -- less than 5 args break out end end if 5 == #out then -- when we have seen five args there may bemore local i = 6; -- initialize the indexer to the sixth positional parameter while args[i] do -- in case there are too many authors loop through the authors looking for a year if is_year (args[i], args) then -- if a year out[5] = args[i]; -- overwrite whatever was in args[5] with year break; -- and abandon the search end i = i + 1; -- bump the indexer end end return mw.uri.anchorEncode ('CITEREF' .. table.concat (out)); end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { harvard_citation = harvard_citation, sfn = sfn, sfnm = sfnm, sfnref = sfnref, }; 1900e2ea7aff0f4023cd9a8f39ece502cc07e045 Template:ErrorBar2 10 151 317 2021-09-18T19:14:24Z Canopus >Andrybak 0 move documentation to /doc wikitext text/x-wiki <includeonly>{{#if:{{{2|}}}|{{#ifexpr: abs({{{2}}}) > abs({{{1}}} * {{{3}}})|approx. {{rnd|{{{1}}}|-{{order of magnitude|{{{2}}}}}}}|{{rnd|{{{1}}}|-{{order of magnitude|{{{2}}}}} }} ± {{rnd|{{{2}}}|-{{order of magnitude|{{{2}}}}} }} }} |{{{1}}} }}</includeonly><noinclude> {{documentation}} </noinclude> 7d3a83f90aace7dc6b51a308b64364e74e8bc666 Kepler 0 26 54 2021-10-05T05:42:36Z Johannes Kepler>Prakhar 0 wikitext text/x-wiki Johannes Kepler was a German [[astronomer]], [[mathematician]], [[astrologer]], natural philosopher and writer on music.[5] He is a key figure in the 17th-century Scientific Revolution, best known for his laws of planetary motion, and his books Astronomia nova, Harmonice Mundi, and Epitome Astronomiae Copernicanae. These works also provided one of the foundations for [[Isaac Newton]] theory of universal gravitation([[Gravity]]). {| class="wikitable" |+Facts |- |Born |27 December 1571 Free Imperial City of Weil der Stadt, Holy Roman Empire |- |Died |15 November 1630 (aged 58) |- |Nationality |German |- |Known for |[[Kepler's laws of planetary motion]] Kepler conjecture Rudolphine Tables |- |Fields |[[Astronomy]], [[astrology]], [[mathematics]], natural philosophy |} 3645e8bbf01a9572c47839bad9c98471c4335cf1 Template:Cite simbad 10 165 345 2021-10-20T19:49:45Z Canopus >MusikBot II 0 Changed protection settings for "[[Template:Cite simbad]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 3956 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require extended confirmed access] (indefinite) [Move=Require extended confirmed access] (indefinite)) wikitext text/x-wiki {{cite web |title={{{title|<noinclude>Title</noinclude>}}} |url=http://simbad.u-strasbg.fr/simbad/sim-basic?Ident{{=}}{{urlencode:{{{title|HD 20794}}}}} |work=[[SIMBAD]] |publisher=[[Centre de données astronomiques de Strasbourg]] |access-date={{{access-date|{{{accessdate|}}}}}} |mode={{{mode|}}} |postscript={{{postscript|}}} }}<noinclude> {{documentation}} </noinclude> b219ca85a3c3d762999e98b05adb0b273a17f2b5 Template:Cite OED 10 130 275 2021-11-08T19:22:23Z Canopus >Twinsday 0 link publisher wikitext text/x-wiki {{#invoke:template wrapper|{{#if:{{{_debug|}}}|list|wrap}}|_template=cite dictionary |_exclude=id, short, term, _debug |url={{#ifeq:{{{term|{{{1|}}}<!-- -->}}}|<!--not set-->| |{{#if:{{{id|}}} |https://www.oed.com/view/Entry/{{{id}}} |https://oed.com/search?searchType=dictionary&q={{urlencode:{{{term|{{{1|}}}}}}}} }} }} |url-access={{#if:{{{term|}}}{{{1|}}}{{{id|}}}|subscription}} |title={{{term|{{{1|}}}}}} |dictionary=[[Oxford English Dictionary]] |publisher={{#if:{{{short|}}}||[[Oxford University Press]]}} |edition={{#if:{{{short|}}}||Online}} |ref={{#if:{{{term|}}}{{{1|}}}{{{id|}}}|{{SfnRef|Reference-OED-{{{term|{{{1|}}}}}}}}}} }}{{#if:{{{short|}}}| |&nbsp;{{OEDsub|sentence={{#ifeq:{{{mode|cs1}}}|cs1|yes|no}}}}<!---->}}<noinclude> {{documentation}} </noinclude> c4826a4de9a2fb0fb19a568c15f96013d914f71d Module:Navbar 828 110 235 2021-11-13T05:33:43Z Canopus >Izno 0 remove unnecessary line Scribunto text/plain local p = {} local cfg = mw.loadData('Module:Navbar/configuration') local function get_title_arg(is_collapsible, template) local title_arg = 1 if is_collapsible then title_arg = 2 end if template then title_arg = 'template' end return title_arg end local function choose_links(template, args) -- The show table indicates the default displayed items. -- view, talk, edit, hist, move, watch -- TODO: Move to configuration. local show = {true, true, true, false, false, false} if template then show[2] = false show[3] = false local index = {t = 2, d = 2, e = 3, h = 4, m = 5, w = 6, talk = 2, edit = 3, hist = 4, move = 5, watch = 6} -- TODO: Consider removing TableTools dependency. for _, v in ipairs(require ('Module:TableTools').compressSparseArray(args)) do local num = index[v] if num then show[num] = true end end end local remove_edit_link = args.noedit if remove_edit_link then show[3] = false end return show end local function add_link(link_description, ul, is_mini, font_style) local l if link_description.url then l = {'[', '', ']'} else l = {'[[', '|', ']]'} end ul:tag('li') :addClass('nv-' .. link_description.full) :wikitext(l[1] .. link_description.link .. l[2]) :tag(is_mini and 'abbr' or 'span') :attr('title', link_description.html_title) :cssText(font_style) :wikitext(is_mini and link_description.mini or link_description.full) :done() :wikitext(l[3]) :done() end local function make_list(title_text, has_brackets, displayed_links, is_mini, font_style) local title = mw.title.new(mw.text.trim(title_text), cfg.title_namespace) if not title then error(cfg.invalid_title .. title_text) end local talkpage = title.talkPageTitle and title.talkPageTitle.fullText or '' -- TODO: Get link_descriptions and show into the configuration module. -- link_descriptions should be easier... local link_descriptions = { { ['mini'] = 'v', ['full'] = 'view', ['html_title'] = 'View this template', ['link'] = title.fullText, ['url'] = false }, { ['mini'] = 't', ['full'] = 'talk', ['html_title'] = 'Discuss this template', ['link'] = talkpage, ['url'] = false }, { ['mini'] = 'e', ['full'] = 'edit', ['html_title'] = 'Edit this template', ['link'] = title:fullUrl('action=edit'), ['url'] = true }, { ['mini'] = 'h', ['full'] = 'hist', ['html_title'] = 'History of this template', ['link'] = title:fullUrl('action=history'), ['url'] = true }, { ['mini'] = 'm', ['full'] = 'move', ['html_title'] = 'Move this template', ['link'] = mw.title.new('Special:Movepage'):fullUrl('target='..title.fullText), ['url'] = true }, { ['mini'] = 'w', ['full'] = 'watch', ['html_title'] = 'Watch this template', ['link'] = title:fullUrl('action=watch'), ['url'] = true } } local ul = mw.html.create('ul') if has_brackets then ul:addClass(cfg.classes.brackets) :cssText(font_style) end for i, _ in ipairs(displayed_links) do if displayed_links[i] then add_link(link_descriptions[i], ul, is_mini, font_style) end end return ul:done() end function p._navbar(args) -- TODO: We probably don't need both fontstyle and fontcolor... local font_style = args.fontstyle local font_color = args.fontcolor local is_collapsible = args.collapsible local is_mini = args.mini local is_plain = args.plain local collapsible_class = nil if is_collapsible then collapsible_class = cfg.classes.collapsible if not is_plain then is_mini = 1 end if font_color then font_style = (font_style or '') .. '; color: ' .. font_color .. ';' end end local navbar_style = args.style local div = mw.html.create():tag('div') div :addClass(cfg.classes.navbar) :addClass(cfg.classes.plainlinks) :addClass(cfg.classes.horizontal_list) :addClass(collapsible_class) -- we made the determination earlier :cssText(navbar_style) if is_mini then div:addClass(cfg.classes.mini) end local box_text = (args.text or cfg.box_text) .. ' ' -- the concatenated space guarantees the box text is separated if not (is_mini or is_plain) then div :tag('span') :addClass(cfg.classes.box_text) :cssText(font_style) :wikitext(box_text) end local template = args.template local displayed_links = choose_links(template, args) local has_brackets = args.brackets local title_arg = get_title_arg(is_collapsible, template) local title_text = args[title_arg] or (':' .. mw.getCurrentFrame():getParent():getTitle()) local list = make_list(title_text, has_brackets, displayed_links, is_mini, font_style) div:node(list) if is_collapsible then local title_text_class if is_mini then title_text_class = cfg.classes.collapsible_title_mini else title_text_class = cfg.classes.collapsible_title_full end div:done() :tag('div') :addClass(title_text_class) :cssText(font_style) :wikitext(args[1]) end return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = cfg.templatestyles } } .. tostring(div:done()) end function p.navbar(frame) return p._navbar(require('Module:Arguments').getArgs(frame)) end return p a5c8d3a8f8beb18984ea7f145ddbdf88a065d23e Module:Navbar/configuration 828 111 237 2021-11-13T05:39:10Z Canopus >Izno 0 well, since I edited the other one... Scribunto text/plain return { ['templatestyles'] = 'Module:Navbar/styles.css', ['box_text'] = 'This box: ', -- default text box when not plain or mini ['title_namespace'] = 'Template', -- namespace to default to for title ['invalid_title'] = 'Invalid title ', ['classes'] = { -- set a line to nil if you don't want it ['navbar'] = 'navbar', ['plainlinks'] = 'plainlinks', -- plainlinks ['horizontal_list'] = 'hlist', -- horizontal list class ['mini'] = 'navbar-mini', -- class indicating small links in the navbar ['this_box'] = 'navbar-boxtext', ['brackets'] = 'navbar-brackets', -- 'collapsible' is the key for a class to indicate the navbar is -- setting up the collapsible element in addition to the normal -- navbar. ['collapsible'] = 'navbar-collapse', ['collapsible_title_mini'] = 'navbar-ct-mini', ['collapsible_title_full'] = 'navbar-ct-full' } } bbf3d86b48a5b40835e8e232ae9821e6bca390ec Energy 0 25 52 2021-11-20T11:18:31Z Energy >Prakhar 0 Created page with "Energy of a body is defined as the capacity or ability of the body to do [[Work]]. ==Forms of energy== ===Mechanical energy=== It includes kinetic and potential energy. '''Ki..." wikitext text/x-wiki Energy of a body is defined as the capacity or ability of the body to do [[Work]]. ==Forms of energy== ===Mechanical energy=== It includes kinetic and potential energy. '''Kinetic energy''' The energy possessed by a body by the virtue of its motion is called kinetic energy. An object in motion has the ability to do work and hence possesses kinetic energy. Examples of Kinetic Energy (1) Wind possesses kinetic energy and can run wind mill. (1) The kinetic energy of flowing water is used to generate electricity. (ii) A bullet fired from a gun possesses kinetic energy and can penetrate a target. Formula Kinetic energy = 1/2 *mv² Where m = mass and v² = velocity squared '''Potential energy''' The energy possessed by a body by the virtue of its position([[displacement]]) or its configuration (shape or size) is called potential energy. An object may have the capacity of doing work as a result of its position in a gravitational([[gravity]]) field, an electric field or a magnetic field. Potential energy may be positive or negative. Potential energy is often referred as stored energy. Examples of Potential Energy (1) The heavy ball of a demolition machine has potential energy when it is held at an elevated position. (i) A stone lying on the ground has no energy so it cannot do any work. If this stone is lifted to the roof of a house, the work has been done in lifting this stone against the force of gravity. This work gets stored up in the stone in the form of potential energy. (ii) The water stored at height in a dam has potential energy. If it is allowed to fall, the falling water has the ability to rotate turbine to generate electricity. (M) A stone resting on the edge of a cliff has potential energy due to its position in the earth's gravitational field. If it falls, the force of gravity which is equal to the stone's weight will act on it until it strikes the ground. The stone's potential energy is equal to the product of its weight and distance it can fall through. (1) Elastic Potential Energy The energy possessed by a body due to the change in its shape is called as elastic potential energy. The change in shape of the body can be brought by compressing, stretching or bending. For this change, some work has to be done. This work gets stored in the form of elastic potential energy. When this deformed body is released it regains its original position and potential energy is given out in some other form of energy. (B) "The gravitational potential energy of an object at a point above the ground is defined as the as the work done is raising it from the ground to that point against gravity without any [[acceleration]]" Formula Work (w) = Mass (M) * Gravity (g) * Displacement (S) or w = mg * s Potential energy = mg * h ===Heat energy=== Heat can be defined as the form of energy that is transferred between two points due to the presence of a [[temperature]] difference between the two points. When water boils, it changes to steam. The steam possesses heat energy because it has the ability to do work such as to run stear engines, turbine etc. The heat produced by the burning of petrol in a car engine provides the energy needed to run the car. ===Nuclear energy=== The energy stored in the nucleus of an atom is called nuclear energy. The energy stored in the nuclei of atoms can be obtained by carrying out two types of nuclear reactions called nuclear fusion and nuclear fission. c9ad0cf3f0a960b707ef98e06b087a2ec4630142 Template:Authority control 10 90 195 2021-11-22T21:18:20Z Canopus >MSGJ 0 add extralist to list of recognised parameters wikitext text/x-wiki {{#invoke:Authority control|authorityControl}}<noinclude>{{Documentation}}</noinclude><includeonly><noinclude> </noinclude>{{#switch:{{NAMESPACE}}||{{ns:14}}=<noinclude> Only articles and categories. </noinclude>{{#invoke:Check for unknown parameters|check|arts|state|extralist|ignoreblank=1|showblankpositional=1|unknown=[[Category:Pages using authority control with parameters|_VALUE_]]|preview=Page using [[Template:Authority control]] with "_VALUE_", please move this to Wikidata if possible}} }}</includeonly> e90b2d4067a752dad843f562fc9e4114bf560c8a Module:IPAc-en/phonemes 828 84 183 2021-11-23T07:28:18Z Canopus >Nardog 0 Reverted 1 edit by [[Special:Contributions/Kwamikagami|Kwamikagami]] ([[User talk:Kwamikagami|talk]]): Please seek consensus first Scribunto text/plain -- This module contains phoneme data for [[Module:IPAc-en]]. return { -- CONSONANTS { code = "b", label = "b", tooltip = "'b' in 'buy'", }, { code = "d", label = "d", tooltip = "'d' in 'dye'", }, { code = "dj", aliases = {"dy", "dʲ"}, label = "dj", tooltip = "/dj/: 'd' in 'dew'", }, { code = "dʒ", aliases = {"dZ", "ʤ"}, label = "dʒ", tooltip = "/dʒ/: 'j' in 'jam'", }, { code = "ð", aliases = {"D"}, label = "ð", tooltip = "/ð/: 'th' in 'this'", }, { code = "f", label = "f", tooltip = "'f' in 'find'", }, { code = "ɡ", aliases = {"g"}, label = "ɡ", tooltip = "/ɡ/: 'g' in 'guy'", }, { code = "h", label = "h", tooltip = "'h' in 'hi'", }, { code = "hw", aliases = {"ʍ"}, label = "hw", tooltip = "/hw/: 'wh' in 'why'", }, { code = "j", aliases = {"y"}, label = "j", tooltip = "/j/: 'y' in 'yes'", }, { code = "k", label = "k", tooltip = "'k' in 'kind'", }, { code = "l", label = "l", tooltip = "'l' in 'lie'", }, { code = "lj", aliases = {"ly", "lʲ"}, label = "lj", tooltip = "/lj/: 'l' in 'lute'", }, { code = "m", label = "m", tooltip = "'m' in 'my'", }, { code = "n", label = "n", tooltip = "'n' in 'nigh'", }, { code = "nj", aliases = {"ny", "nʲ"}, label = "nj", tooltip = "/nj/: 'n' in 'new'", }, { code = "ŋ", aliases = {"N", "ng"}, label = "ŋ", tooltip = "/ŋ/: 'ng' in 'sing'", }, { code = "p", label = "p", tooltip = "'p' in 'pie'", }, { code = "r", aliases = {"ɹ", "ɻ"}, label = "r", tooltip = "'r' in 'rye'", }, { code = "s", label = "s", tooltip = "'s' in 'sigh'", }, { code = "sj", aliases = {"sy", "sʲ"}, label = "sj", tooltip = "/sj/: 's' in 'consume'", }, { code = "ʃ", aliases = {"S", "sh"}, label = "ʃ", tooltip = "/ʃ/: 'sh' in 'shy'", }, { code = "t", label = "t", tooltip = "'t' in 'tie'", }, { code = "tj", aliases = {"ty", "tʲ"}, label = "tj", tooltip = "/tj/: 't' in 'tune'", }, { code = "tʃ", aliases = {"tS", "ʧ", "ch"}, label = "tʃ", tooltip = "/tʃ/: 'ch' in 'China'", }, { code = "θ", aliases = {"T"}, label = "θ", tooltip = "/θ/: 'th' in 'thigh'", }, { code = "θj", aliases = {"θy", "θʲ"}, label = "θj", tooltip = "/θj/: 'th' in 'enthuse'", }, { code = "v", label = "v", tooltip = "'v' in 'vie'", }, { code = "w", label = "w", tooltip = "'w' in 'wind'", }, { code = "z", label = "z", tooltip = "'z' in 'zoom'", }, { code = "zj", aliases = {"zy", "zʲ"}, label = "zj", tooltip = "/zj/: 'Z' in 'Zeus'", }, { code = "ʒ", aliases = {"Z", "zh"}, label = "ʒ", tooltip = "/ʒ/: 's' in 'pleasure'", }, -- VOWELS { code = "ɑː", aliases = {"A:", "ɑ:", "aː", "a:"}, label = "ɑː", tooltip = "/ɑː/: 'a' in 'father'", }, { code = "ɑːr", aliases = {"ɑɹ", "aːr", "a:r", "ɑ:r", "ɑr"}, label = "ɑːr", tooltip = "/ɑːr/: 'ar' in 'far'", }, { code = "ɒ", aliases = {"Q"}, label = "ɒ", tooltip = "/ɒ/: 'o' in 'body'", }, { code = "ɒr", aliases = {"Qr"}, label = "ɒr", tooltip = "/ɒr/: 'or' in 'moral'", }, { code = "æ", aliases = {"ae", "{"}, label = "æ", tooltip = "/æ/: 'a' in 'bad'", }, { code = "ær", aliases = {"aer", "&r", "æɹ"}, label = "ær", tooltip = "/ær/: 'arr' in 'marry'", }, { code = "aɪ", aliases = {"ai", "aI"}, label = "aɪ", tooltip = "/aɪ/: 'i' in 'tide'", }, { code = "aɪər", aliases = {"aɪr", "aIr", "aɪə"}, label = "aɪər", tooltip = "/aɪər/: 'ire' in 'fire'", }, { code = "aʊ", aliases = {"au", "aU"}, label = "aʊ", tooltip = "/aʊ/: 'ou' in 'mouth'", }, { code = "aʊər", aliases = {"aʊr", "aUr", "aʊə", "aur"}, label = "aʊər", tooltip = "/aʊər/: 'our' in 'hour'", }, { code = "ɛ", aliases = {"E"}, label = "ɛ", tooltip = "/ɛ/: 'e' in 'dress'", }, { code = "ɛr", aliases = {"Er"}, label = "ɛr", tooltip = "/ɛr/: 'err' in 'merry'", }, { code = "eɪ", aliases = {"ei", "eI", "eː", "e:"}, label = "eɪ", tooltip = "/eɪ/: 'a' in 'face'", }, { code = "ɛər", aliases = {"eir", "eIr", "e@r", "E@r", "ɛɪɹ", "eɪr", "eːr", "e:r", "ɛəɹ", "ɛə", "ɛːr", "ɛ:r", "ɛː", "ɛ:", "E:", "E:r"}, label = "ɛər", tooltip = "/ɛər/: 'are' in 'bare'", }, { code = "ɛəˈr", aliases = {"ɛə'r", "eəˈr", "eə'r", "e@'r", "E@'r", "ɛːˈr", "E:'r"}, label = "ɛəˈr", tooltip = "/ɛəˈr/: 'ere' in 'thereof'", }, { code = "ɛəˌr", aliases = {"ɛə,r", "eəˌr", "eə,r", "E@,r", "E@%r", "e@,r", "e@%r", "ɛːˌr", "E:,r", "E:%r"}, label = "ɛəˌr", tooltip = "/ɛəˌr/: 'ere' in 'thereof'", }, { code = "ɪ", aliases = {"I", "ᵻ"}, label = "ɪ", tooltip = "/ɪ/: 'i' in 'kit'", }, { code = "ɪr", label = "ɪr", tooltip = "/ɪr/: 'irr' in 'mirror'", }, { code = "iː", aliases = {"i:"}, label = "iː", tooltip = "/iː/: 'ee' in 'fleece'", }, { code = "ɪər", aliases = {"i:r", "iːr", "I@r", "i@r", "ɪəɹ", "iːɹ", "ɪə"}, label = "ɪər", tooltip = "/ɪər/: 'ear' in 'near'", }, { code = "ɪəˈr", aliases = {"ɪə'r", "I@'r"}, label = "ɪəˈr", tooltip = "/ɪəˈr/: 'er' in 'spheroidal'", }, { code = "ɪəˌr", aliases = {"ɪə,r", "I@,r", "I@%r"}, label = "ɪəˌr", tooltip = "/ɪəˌr/: 'er' in 'spheroidal'", }, { code = "oʊ", aliases = {"o:", "oː", "ou", "oU", "@u", "@U", "əʊ", "əu", "oʊ-"}, label = "oʊ", tooltip = "/oʊ/: 'o' in 'code'", }, { code = "ɔː", aliases = {"O", "O:", "ɔ:", "ɒː", "Q:"}, label = "ɔː", tooltip = "/ɔː/: 'au' in 'fraud'", }, { code = "ɔːr", aliases = {"Or", "ɔɹ", "ɔ(r)", "ɔr", "ɔər", "oUr", "ɔəɹ", "ɔʊɹ", "oʊɹ", "oʊr", "oːr", "o:r", "ɔə", "ɔə(r)"}, label = "ɔːr", tooltip = "/ɔːr/: 'ar' in 'war'", }, { code = "ɔɪ", aliases = {"oj", "ɔj", "oi", "oɪ", "ɔi", "OI", "oy"}, label = "ɔɪ", tooltip = "/ɔɪ/: 'oi' in 'choice'", }, { code = "ɔɪər", aliases = {"ɔɪr", "oyr", "ɔɪə"}, label = "ɔɪər", tooltip = "/ɔɪər/: 'oir' in 'coir'", }, { code = "ʊ", aliases = {"U", "ᵿ"}, label = "ʊ", tooltip = "/ʊ/: 'u' in 'push'", }, { code = "ʊr", aliases = {"Ur"}, label = "ʊr", tooltip = "/ʊr/: 'our' in 'courier'", }, { code = "uː", aliases = {"u:"}, label = "uː", tooltip = "/uː/: 'oo' in 'goose'", }, { code = "ʊər", aliases = {"u:r", "uːr", "u@r", "U@r", "ʊəɹ", "ʊə"}, label = "ʊər", tooltip = "/ʊər/: 'our' in 'tour'", }, { code = "ʊəˈr", aliases = {"ʊə'r", "U@'r"}, label = "ʊəˈr", tooltip = "/ʊəˈr/: 'ur' in 'plurality'", }, { code = "ʊəˌr", aliases = {"ʊə,r", "U@,r", "U@%r"}, label = "ʊəˌr", tooltip = "/ʊəˌr/: 'ur' in 'plurality'", }, { code = "ʌ", aliases = {"V"}, label = "ʌ", tooltip = "/ʌ/: 'u' in 'cut'", }, { code = "ʌr", aliases = {"Vr", "ʌɹ"}, label = "ʌr", tooltip = "/ʌr/: 'urr' in 'hurry'", }, { code = "ɜːr", aliases = {"ɝː", "ɝ", "3r", "3:r", "əːr", "@:r", "ɜɹ", "ɜ(r)", "ɜr"}, label = "ɜːr", tooltip = "/ɜːr/: 'ur' in 'fur'", }, { code = "ə", aliases = {"@"}, label = "ə", tooltip = "/ə/: 'a' in 'about'", }, -- SYLLABIC CONSONANTS { code = "ər", aliases = {"ɚ", "@r", "əɹ", "ə(r)"}, label = "ər", tooltip = "/ər/: 'er' in 'letter'", }, { code = "əl", aliases = {"@l", "ᵊl", "l̩"}, label = "əl", tooltip = "/əl/: 'le' in 'bottle'", }, { code = "ən", aliases = {"@n", "ᵊn", "n̩"}, label = "ən", tooltip = "/ən/: 'on' in 'button'", }, { code = "əm", aliases = {"@m", "ᵊm", "m̩"}, label = "əm", tooltip = "/əm/: 'm' in 'rhythm'", }, -- ARCHIPHONEMES { code = "i", label = "i", tooltip = "/i/: 'y' in 'happy'", }, { code = "u", label = "u", tooltip = "/u/: 'u' in 'influence'", }, -- MARGINAL SEGMENTS { code = "x", label = "x", aliases = {"kh"}, tooltip = "/x/: 'ch' in 'loch'", }, { code = "ʔ", aliases = {"?"}, label = "ʔ", tooltip = "/ʔ/: the catch in 'uh-oh'", }, { code = "ɒ̃", aliases = {"ɑ̃", "ɒ~", "ɑ~", "Q~"}, label = "ɒ̃", tooltip = "/ɒ̃/: nasal 'an' in 'vin blanc'", }, { code = "æ̃", aliases = {"ae~", "{~", "ã", "a~"}, label = "æ̃", tooltip = "/æ̃/: nasal 'in' in 'vin blanc'", }, { code = "ɜː", aliases = {"3", "3:", "ɜ:", "ɜ", "əː", "@:"}, label = "ɜː", tooltip = "/ɜː/: r-less 'ur' in 'nurse'", }, -- SUPRASEGMENTALS { code = "ˈ", aliases = {"'", '"'}, label = "ˈ", tooltip = "/ˈ/: primary stress follows", }, { code = "ˌ", aliases = {",", "%"}, label = "ˌ", tooltip = "/ˌ/: secondary stress follows", }, { code = ".", aliases = {"·"}, label = ".", tooltip = "/./: syllable break", }, { code = "#", label = "#", tooltip = "/#/: morpheme break", }, { code = "!", label = "&#124;", tooltip = "/|/: prosodic break (minor)", }, { code = "!!", aliases = {"‖"}, label = "‖", tooltip = "/‖/: prosodic break (major)", }, -- SEPARATORS -- Tables without tooltip text are used as word separators. In addition to -- not having any tooltip text in the template output, they are not -- underlined. { code = "_", label = "<span class=\"wrap\"> </span>", }, { code = "nbsp", aliases = {"&nbsp;"}, label = " ", }, { code = ",_", label = ",<span class=\"wrap\"> </span>", }, { code = "-", aliases = {"–"}, label = "-", }, { code = "(", label = "(", }, { code = ")", label = ")", }, -- This is useful for highly variable words in place names, which are not -- important to transcribe. { code = "...", label = "&thinsp;...<span class=\"wrap\">&thinsp;</span>", }, -- Obsolete combinations, kept for compatibility { code = "juː", label = "juː", tooltip = "/juː/: 'u' in 'cute'", }, { code = "jʊər", label = "jʊər", tooltip = "/jʊər/: 'ure' in 'cure'", }, } edb55389474ac8485fc15b3386eebeb0c44b7263 Module:Lang-zh 828 150 315 2021-12-05T17:08:57Z Canopus >Pppery 0 Update per edit request Scribunto text/plain require('Module:No globals') local p = {} -- articles in which traditional Chinese preceeds simplified Chinese local t1st = { ["228 Incident"] = true, ["Chinese calendar"] = true, ["Lippo Centre, Hong Kong"] = true, ["Republic of China"] = true, ["Republic of China at the 1924 Summer Olympics"] = true, ["Taiwan"] = true, ["Taiwan (island)"] = true, ["Taiwan Province"] = true, ["Wei Boyang"] = true, } -- the labels for each part local labels = { ["c"] = "Chinese", ["s"] = "simplified Chinese", ["t"] = "traditional Chinese", ["p"] = "pinyin", ["tp"] = "Tongyong Pinyin", ["w"] = "Wade–Giles", ["j"] = "Jyutping", ["cy"] = "Cantonese Yale", ["sl"] = "Sidney Lau", ["poj"] = "Pe̍h-ōe-jī", ["zhu"] = "Zhuyin Fuhao", ["l"] = "lit.", ["tr"] = "trans.", } -- article titles for wikilinks for each part local wlinks = { ["c"] = "Chinese language", ["s"] = "simplified Chinese characters", ["t"] = "traditional Chinese characters", ["p"] = "pinyin", ["tp"] = "Tongyong Pinyin", ["w"] = "Wade–Giles", ["j"] = "Jyutping", ["cy"] = "Yale romanization of Cantonese", ["sl"] = "Sidney Lau romanisation", ["poj"] = "Pe̍h-ōe-jī", ["zhu"] = "Bopomofo", ["l"] = "Literal translation", ["tr"] = "Translation", } -- for those parts which are to be treated as languages their ISO code local ISOlang = { ["c"] = "zh", ["t"] = "zh-Hant", ["s"] = "zh-Hans", ["p"] = "zh-Latn-pinyin", ["tp"] = "zh-Latn", ["w"] = "zh-Latn-wadegile", ["j"] = "yue-Latn-jyutping", ["cy"] = "yue-Latn", ["sl"] = "yue-Latn", ["poj"] = "nan-Latn", ["zhu"] = "zh-Bopo", } local italic = { ["p"] = true, ["tp"] = true, ["w"] = true, ["j"] = true, ["cy"] = true, ["sl"] = true, ["poj"] = true, } local superscript = { ["w"] = true, ["sl"] = true, } -- Categories for different kinds of Chinese text local cats = { ["c"] = "[[Category:Articles containing Chinese-language text]]", ["s"] = "[[Category:Articles containing simplified Chinese-language text]]", ["t"] = "[[Category:Articles containing traditional Chinese-language text]]", } function p.Zh(frame) -- load arguments module to simplify handling of args local getArgs = require('Module:Arguments').getArgs local args = getArgs(frame) return p._Zh(args) end function p._Zh(args) local uselinks = not (args["links"] == "no") -- whether to add links local uselabels = not (args["labels"] == "no") -- whether to have labels local capfirst = args["scase"] ~= nil local t1 = false -- whether traditional Chinese characters go first local j1 = false -- whether Cantonese Romanisations go first local testChar if (args["first"]) then for testChar in mw.ustring.gmatch(args["first"], "%a+") do if (testChar == "t") then t1 = true end if (testChar == "j") then j1 = true end end end if (t1 == false) then local title = mw.title.getCurrentTitle() t1 = t1st[title.text] == true end -- based on setting/preference specify order local orderlist = {"c", "s", "t", "p", "tp", "w", "j", "cy", "sl", "poj", "zhu", "l", "tr"} if (t1) then orderlist[2] = "t" orderlist[3] = "s" end if (j1) then orderlist[4] = "j" orderlist[5] = "cy" orderlist[6] = "sl" orderlist[7] = "p" orderlist[8] = "tp" orderlist[9] = "w" end -- rename rules. Rules to change parameters and labels based on other parameters if args["hp"] then -- hp an alias for p ([hanyu] pinyin) args["p"] = args["hp"] end if args["tp"] then -- if also Tongyu pinyin use full name for Hanyu pinyin labels["p"] = "Hanyu Pinyin" end if (args["s"] and args["s"] == args["t"]) then -- Treat simplified + traditional as Chinese if they're the same args["c"] = args["s"] args["s"] = nil args["t"] = nil elseif (not (args["s"] and args["t"])) then -- use short label if only one of simplified and traditional labels["s"] = labels["c"] labels["t"] = labels["c"] end local body = "" -- the output string local params -- for creating HTML spans local label -- the label, i.e. the bit preceeding the supplied text local val -- the supplied text -- go through all possible fields in loop, adding them to the output for i, part in ipairs(orderlist) do if (args[part]) then -- build label label = "" if (uselabels) then label = labels[part] if (capfirst) then label = mw.language.getContentLanguage():ucfirst(label) capfirst = false end if (uselinks) then label = "[[" .. wlinks[part] .. "|" .. label .. "]]" end if (labels[part] ~= "lit.") then label = label .. "&#58;" else label = "<small>" .. label .. "</small>" end label = label .. " " end -- build value val = args[part] if (cats[part]) and mw.title.getCurrentTitle().namespace == 0 then -- if has associated category AND current page in article namespace, add category val = cats[part] .. val end if (ISOlang[part]) then -- add span for language if needed params = {["lang"] = ISOlang[part]} val = mw.text.tag({name="span",attrs=params, content=val}) elseif ((part == "l") or (part == "tr")) then -- put literals in quotes val = "'" .. val .. "'" end if (italic[part]) then -- italicise val = "<i>" .. val .. "</i>" end if string.match(val, "</?sup>") then val = val.."[[Category:Pages using template Zh with sup tags]]" end if (superscript[part]) then -- superscript val = val:gsub("(%d)", "<sup>%1</sup>"):gsub("(%d)</sup>%*<sup>(%d)", "%1*%2"):gsub("<sup><sup>([%d%*]+)</sup></sup>", "<sup>%1</sup>") end -- add both to body body = body .. label .. val .. "; " end end if (body > "") then -- check for empty string return string.sub(body, 1, -3) -- chop off final semicolon and space else --no named parameters; see if there's a first parameter, ignoring its name if (args[1]) then -- if there is treat it as Chinese label = "" if (uselabels) then label = labels["c"] if (uselinks) then label = "[[" .. wlinks["c"] .. "|" .. label .. "]]" end label = label .. "&#58; " end -- default to show links and labels as no options given if mw.title.getCurrentTitle().namespace == 0 then -- if current page in article namespace val = cats["c"] .. args[1] else val = args[1] end params = {["lang"] = ISOlang["c"]} val = mw.text.tag({name="span",attrs=params, content=val}) return label .. val end return "" end end return p 784d83ce2141b8e5828575b09c81e5f62a637998 Template:Main other 10 66 147 2021-12-10T16:08:06Z Canopus >Xaosflux 0 <!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! --> wikitext text/x-wiki {{#switch: <!--If no or empty "demospace" parameter then detect namespace--> {{#if:{{{demospace|}}} | {{lc: {{{demospace}}} }} <!--Use lower case "demospace"--> | {{#ifeq:{{NAMESPACE}}|{{ns:0}} | main | other }} }} | main = {{{1|}}} | other | #default = {{{2|}}} }}<noinclude> {{documentation}} <!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! --> </noinclude> 86ad907ffeea3cc545159e00cd1f2d6433946450 Module:Footnotes/anchor id list 828 103 221 2021-12-20T18:02:30Z Canopus >Trappist the monk 0 Scribunto text/plain require('Module:No globals'); local data = mw.loadData ('Module:Footnotes/anchor id list/data'); local whitelist = mw.loadData ('Module:Footnotes/whitelist'); local Lang_obj = mw.language.getContentLanguage(); -- used by template_list_add() to uppercase first letter of template name TODO: better way to do that? local redirects_date = { ['date'] = true, ['datetomos'] = true, ['formatdate'] = true, ['isotodmymdy'] = true, ['isotomos'] = true, } local redirects_patent = { -- special case cs1-like templates because uses different parameters for name and date in anchor ID ['Cite patent'] = true, ['Citeref patent'] = true, ['Ref patent'] = true, } local redirects_sfnref = { ['sfnref'] = true, ['harvid'] = true, } local aliases_author = { -- these use pseudo-patterns in the same way as cs1|2; '#' represents 1 or more enumerator digits 'last#', 'author#', 'surname#', 'author-last#', 'author#-last', 'subject#', 'host#', } local aliases_contributor = { 'contributor#', 'contributor-last#', 'contributor#-last', 'contributor-surname#', 'contributor#-surname', } local aliases_editor = { 'editor#', 'editor-last#', 'editor#-last', 'editor-surname#', 'editor#-surname', } local aliases_harvc_author = { 'last#', 'author#', } local aliases_inventor = { -- cite patent 'inventor#', 'inventor-last#', 'inventor#-last', 'inventor-surname#', 'inventor#-surname', 'invent#', 'invent-#', } local alias_patterns_date = { -- normal lua patterns for most cs1|2-like templates '|%s*year%s*=%s*', '|%s*date%s*=%s*', '|%s*publication%-?date%s*=%s*', '|%s*air%-?date%s*=%s*', } local alias_patterns_harvc_date = { -- normal lua patterns for harvc template '|%s*anchor%-year%s*=%s*', '|%s*year%s*=%s*', } local alias_patterns_patent_date = { -- normal lua patterns for cite patent templates '|%s*issue%-date%s*=%s*', '|%s*gdate%s*=%s*', '|%s*publication%-date%s*=%s*', '|%s*pubdate%s*=%s*', } local patterns_date = { -- normal lua patterns '(%d%d%d%d–%d%d%d%d%l?)$', -- YYYY–YYYY four-digit year range at end (Season YYYY–YYYY); with or without dab '^(%d%d%d%d–%d%d%l?)$', -- YYYY–YY two-digit year range; with or without dab '^(c%. %d%d%d%d?%l?)$', -- three- or four-digit circa year; with or without dab '(%d%d%d%d?%l?)$', -- three- or four-digit year at end of date (dmy or mdy); with or without dab '^(%d%d%d%d?%l?)', -- three- or four-digit year at beginning of date (ymd or YYYY); with or without dab '^(n%.d%.%l?)$', -- 'no date' with dots; with or without dab '^(nd%l?)$', -- 'no date' without dots; with or without dab } local patterns_tags = { '<nowiki>.-</nowiki>', '<!%-%-.-%-%->', '<pre>.-</pre>', '<syntaxhighlight.->.-</syntaxhighlight>', '<source.->.-</source>', -- deprecated alias of syntaxhighlight tag } local template_skip = { -- templates to be skipped for whatever reason; mostly because they resemble cs1-like templates ['Citation-attribution'] = true, } local Article_content; local anchor_id_list = {}; -- exported tables local template_list = {}; local article_whitelist = {}; --[[--------------------------< A R T I C L E _ C O N T E N T _ G E T >---------------------------------------- get article content, remove certain html-like tags and their content so that this code doesn't include any citation templates inside the tags as valid tagets; they are not. ]] local function article_content_get () if not Article_content then Article_content = mw.title.getCurrentTitle():getContent() or ''; -- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625 for _, tag in ipairs (patterns_tags) do Article_content = Article_content:gsub (tag, ''); -- remove certain html-like tags and their content end end end --[[--------------------------< S F N R E F _ G E T >---------------------------------------------------------- make an anchor id from the contents of {{sfnref}} or {{harvid}}. this function assumes that {{sfnref}} and {{harvid}} are correctly formed. ]] local function sfnref_get (template) template = template:gsub ('{{%s*(.-)%s*}}', '%1'); -- strip bounding template markup and trim local parts = mw.text.split (template, '%s*|%s*'); -- split at the pipe and remove extraneous space characters local anchor_id = {}; if redirects_sfnref[parts[1]:lower()] then anchor_id[1] = 'CITEREF'; else return nil; -- not an sfnref or harvid template end local i = 2; -- indexer into parts{} table local j = 2; -- indexer into anchor_id{} table which already has 'CITEREF' at [1] while parts[i] and 7 > j do -- loop through what should be just positional parameters for names and year (2-6 four names and a date) if not parts[i]:find ('=') then -- look for equal sign (named paraneter in a template that doesn't support named parameters) anchor_id[j] = parts[i]; -- positional parameters are saved j = j+1; -- bump the anchor_id{} indexer end i = i+ 1; -- bump the parts{} indexer end return table.concat (anchor_id, ''); end --[[--------------------------< D A T E _ G E T >-------------------------------------------------------------- extract year from one of |year=, |date=, |publicationdate=, or |publication-date in that order. Does not error check (that is left to the cs1|2 templates to do) also gets date from |<date alias>={{date|...}} ]] local function date_get (template, aliases) local date; local rvalue; for _, pattern in ipairs (aliases) do -- spin through the date alias patterns rvalue = tostring(template):match (pattern); -- is this |<date alias>= used (tostring() because something makes match() think template is a table) if rvalue then rvalue = tostring(template):match (pattern .. '(%b{})'); -- is rvalue a template? if rvalue then rvalue = rvalue:gsub ('{{%s*(.-)%s*}}', '%1'); -- strip bounding template markup and trim local parts = mw.text.split (rvalue, '%s*|%s*'); -- split at the pipe and remove extraneous space characters if redirects_date[parts[1]:lower()] then -- if parts[1] names {{date}} or redirect rvalue = parts[2]; -- assume that date template is properly formed, first positional parameter is the date else return ''; -- |date= holds some other template than {{date}} or redirect end else rvalue = template:match (pattern .. '([^|}]+)'); if rvalue then -- if rvalue is something rvalue = mw.text.trim (rvalue); -- trim it end if not rvalue or '' == rvalue then -- if rvale was nothing or trimed to nothing rvalue = nil; -- ensure that it is unset so we can try the next parameter in the list end end if rvalue then for _, pattern in ipairs (patterns_date) do -- spin through the recognized date formats date = rvalue:match (pattern); -- attempt to extract year portion according to the pattern if date then return date; -- matched so return; end end break; -- found a date but it was malformed so abandon end end end return ''; -- no date param or date param doesn't hold a recognized date; empty string for concatenation end --[[--------------------------< V N A M E S _ G E T >---------------------------------------------------------- extract names from |vauthors= or |veditors=; there is no |vcontributors= parameter. splits the v parameter value at the comma; correctly handles accept-as-witten markup when used to wrap a comma- separated names (corporate) ]] local function vnames_get (params, vparam) local vnames = {}; -- first four author or editor names go here local split = {}; -- temp table to assist in decoding accept-as-witten-markup if params[vparam] then -- test for |vauthors= or |veditor= split = mw.text.split (params[vparam], '%s*,%s*'); -- this will separate portions of ((Black, Brown, White, an Co.)) local i = 1; -- an indexer while split[i] do if split[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of comma-separated accept-as-witten; this segment has the opening doubled parens local name = split[i]; i=i+1; -- bump indexer to next segment while split[i] do name = name .. ', ' .. split[i]; -- concatenate with previous segments if split[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parens break; -- and done reassembling so end i=i+1; -- bump indexer end table.insert (vnames, name); -- and add accept-as-witten name to the vnames table else table.insert (vnames, split[i]); -- and add name to the vnames table end i=i+1; -- bump indexer if 5 == i then break; end -- limit to four names end for i, vname in ipairs (vnames) do if not vname:match ('%(%(.-%)%)') then -- without accept-this-value-as-written markup vnames[i] = vname:gsub ('(.-)%s+%u+$', '%1'); -- extract and save surname(s) end end for i, vname in ipairs (vnames) do -- repeat, this time for accept-this-value-as-written markup vnames[i] = vname:gsub ('%(%((.-)%)%)', '%1'); -- remove markup if present and save the whole name end end return 0 ~= #vnames and table.concat (vnames) or nil -- return a concatenation of the vnames; nil else end --[[--------------------------< N A M E S _ G E T >------------------------------------------------------------ cs1|2 makes anchor id from contributor, author, or editor name-lists in that order get the names from the cs1|2 template; if there are no contributor names, try author names, then try editor names. returns concatenated names in enumeration order when successful; nil else empty name (nameholding parameter n is present without value) and missing name (nameholding parameter n is not present) are included as empty string with all other names ]] local function names_get (params, aliases_list) local names = {}; -- first four author or editor names go here local enum_alias; -- alias with '#' replaced with a digit for enum=1, 4 do -- four names only for i, alias in ipairs (aliases_list) do if not names[enum] then -- hanven't found a previous alias with this [enum]? see if we can find this alias with this enum enum_alias = alias:gsub ('#', enum); -- replace '#' to make 'lastn' if 1 == enum then -- because |last= and last1= are exact aliases if params[enum_alias] then -- test |last1= first names[enum] = params[enum_alias]; -- found so save the value assigned to |last1= break; -- next enum else enum_alias = alias:gsub ('#', ''); -- replace '#' to make 'last' if params[enum_alias] then names[enum] = params[enum_alias]; -- found so save the value assigned to |last= break; -- next enum end end else -- here for enum 2, 3, 4 if params[enum_alias] then names[enum] = params[enum_alias]; -- found so save the value assigned to |lastn= break; -- next enum end end end end end for enum=1, 4 do -- spin through the names table and local name = names[enum]; if not name then -- when nameholding parameter n is not present (nil) name = ''; -- convert to empty string for concatenation end name = name:gsub('%(%((.-)%)%)', '%1'); -- remove accept-as-written markup if present names[enum] = name; -- save the modified name end local name_str = table.concat (names); -- concatenate the names return '' ~= name_str and name_str or nil; -- return the concatenation if not empty string; nil else end --[[--------------------------< T E M P L A T E _ S T R I P >-------------------------------------------------- removes the citation or havrc template's {{ and }} markup then removes, in whole, any templates found inside the citation or harvc template. Templates are not allowed in parameters that are made part of COinS metadata; yet, they will appear. cs1|2 does not see the template markup but instead sees the result of the template as html. cs1|2 strips the html which leaves the displayed value for the anchor id. We can't do that here so, because templates aren't allowed in parameters, we simply discard any templates found in the cs1|2 template. this may leave a |lastn= parameter empty which will be treated as if it were really empty as cs1|2 do (three authors, |last2= empty -> CITEREFLast1Last3YYYY (the harv and sfn render: 'Last1, & Last3 YYYY' with CITEREFLast1Last3YYYY). ]] local function template_strip (template) template = template:gsub ('^{{%s*', ''):gsub ('%s*}}$', '', 1); -- remove outer {{ and }} (cs1|2 template delimiters with trailing/leading whitespace) template = template:gsub ('%b{}', ''); -- remove any templates from the cs1|2 template return template; end --[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >---------------------------------- Returns a string where all of lua's magic characters have been escaped. This is important because functions like string.gsub() treat their pattern and replace strings as patterns, not literal strings. ]] local function escape_lua_magic_chars (argument) argument = argument:gsub("%%", "%%%%"); -- replace % with %% argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other lua magic pattern characters return argument; end --[=[-------------------------< W I K I L I N K _ S T R I P >-------------------------------------------------- Wikilink markup does not belong in an anchor id and can / does confuse the code that parses apart citation and harvc templates so here we remove any wiki markup: [[link|label]] -> label [[link]] -> link ]=] local function wikilink_strip (template) for wikilink in template:gmatch ('%[%b[]%]') do -- get a wikilink template = template:gsub ('%[%b[]%]', '__57r1P__', 1); -- install a marker if wikilink:match ('%[%[.-|(.-)%]%]') then wikilink = wikilink:match ('%[%[.-|(.-)%]%]'); -- extract label from complex [[link|label]] wikilink else wikilink = wikilink:match ('%[%[(.-)%]%]'); -- extract link from simple [[link]] wikilinks end wikilink = escape_lua_magic_chars (wikilink); -- in case there are lua magic characters in wikilink template = template:gsub ('__57r1P__', wikilink, 1); -- replace the marker with the appropriate text end return template; end --[[--------------------------< T E M P L A T E _ N A M E _ G E T >-------------------------------------------- return the citation or harvc template's name; convert to lower case and trim leading and trailing whitespace; when the template is a sandbox the subpage portion of the template name is omitted from the returned template name {{Cite book/new |...}} returns cite book ]] local function template_name_get (template) local template_name = template:match ('^{{%s*([^/|}]+)'); -- get template name; ignore subpages ~/new, ~/sandbox; parser functions if not template_name or template_name:match ('^#') then -- parser functions, magic words don't count as templates return nil; -- could not get template name from (possibly corrupt) template; extraneous opening { mid template can cause this; end; template_name = template_name:gsub ('%s*$', ''); -- trim trailing whitespace; leading whitespace already removed return Lang_obj:ucfirst (template_name); -- first character in template name must be uppercase (same as canonical template name) TODO: better way to do this? end --[[--------------------------< T E M P L A T E _ P A R A M S _ G E T >---------------------------------------- parse apart a template's parameters and store in the params table where key is the parameter's name and value is the parameter's value; empty parameters are not saved ]] local function template_params_get (template, params_t) template = wikilink_strip (template); -- because piped wikilinks confuse code that builds params_t{} and because wikilinks not allowed in an anchor id -- strip templates after getting |ref= value because |ref={{sfnref}} and |ref={{harvid}} are allowed template = template_strip (template); -- because template markup can confuse code that builds params_t{} and because templates in name parameters are not allowed local temp_t = mw.text.split (template, '%s*|%s*'); --split on the pipe for _, param in ipairs (temp_t) do if param:find ('=', 1, true) then -- a named parameter? local k, v = param:match ('%s*([^=]-)%s*=%s*([^|}]+)'); if v then -- there must be a value if '' ~= v and not v:match ('^%s$') then -- skip when value is empty string or only whitespace params_t[k] = mw.text.trim (v); -- add trimmed value else end end end end end --[[--------------------------< C I T E R E F _ M A K E _ H A R V C >------------------------------------------ makes anchor_id from {{harvc}} or redirects ]] local function anchor_id_make_harvc (template) local date = date_get (template, alias_patterns_harvc_date); -- get date; done here because might be in {{date}}; return date if valid; empty string else local anchor_id; local params = {}; -- table of harvc parameters local id; -- custom anchor id for this {{harvc}} template id = template:match ('|%s*id%s*=%s*(%b{})'); -- in case |id={{sfnref}}; done here because templates will be stripped template_params_get (template, params); -- build a table of template parameters and their values; this strips wikilinks and templates if id then -- when set is {{sfnref}} or {{harvid}} template return sfnref_get (id); -- returns content of {{sfnref}} or {{harvid}}; nil else end if params.id then -- custom anchor for this {{harvc}} template (text) return params.id; -- |id= value as written end anchor_id = names_get (params, aliases_harvc_author); -- get the harvc contributor names if anchor_id then -- if names were gotten return 'CITEREF' .. anchor_id .. date; end return nil; -- no names; no anchor_id end --[[--------------------------< A N C H O R _ I D _ M A K E _ W R A P P E R >---------------------------------- for wrapper templates inspect externally visible |ref= to decide what to do: |ref= - empty or missing: get names and date from whitelist defaults; override defaults from externally visible template parameters |ref=harv - same as empty or missing |ref={{SfnRef|name|name|name|name|year}} - assemble an anchor id from {{sfnref}} positional parameters |ref={{Harvid|name|name|name|name|year}} - assemble an anchor id from {{harvid}} positional parameters |ref=none - skip; do nothing because an anchor id intentionally suppressed; TODO: keep with a type code of '0'? |ref=<text> - save param value because may match an anchor id override value in {{harv}} template |ref= parameter or {{harvc}} |id= parameter ]] local function anchor_id_make_wrapper (template) local ref; -- content of |ref= local template_name; -- name of the template local anchor_id; -- the assembled anchor id from this template local date; local name_default; local date_default; local vol; local params = {}; -- table of template parameters template_name = template_name_get (template); -- get first char uppercase trimmed template name; ignore subpages ~/new, ~/sandbox if not template_name or template_skip[template_name] then return nil; -- could not extract template name from (possibly corrupted) template (extraneous opening { in the template will cause this) end date = date_get (template, alias_patterns_date); -- get date; done here because might be in {{date}} -- if '' == date then -- date = whitelist.wrapper_templates[template_name][2] or ''; -- no externally visible date so get default date -- end ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}} because we will strip templates from the wrapper template if not ref then if template:match ('|%s*ref%s*=([^|}]+)') then -- |ref={{template}} not found; if there is a |ref= param with an assigned value ref = template:match ('|%s*ref%s*=([^|}]+)'); -- get the value; whitespace is a 'value' if ref then -- nil when |ref=|... or when |ref=}} (no spaces between assignment operator and pipe or closing brace) ref = mw.text.trim (ref); -- something, could be just whitespace, so trim leading / trailing whitespace if '' == ref then -- trimming a string of whitespace makes an empty string ref = nil; -- make empty ref same as missing ref end end end end template_params_get (template, params); -- build a table of template parameters and their values if whitelist.wrapper_templates[template_name][1] then -- is this wrapper a simple-default wrapper? name_default = whitelist.wrapper_templates[template_name][1]; -- get the default names date_default = whitelist.wrapper_templates[template_name][2]; -- get the default date else vol = params['volume'] or 'default'; if not whitelist.wrapper_templates[template_name][vol] then -- make sure this volume exists vol = 'default'; -- doesn't exist, use default volume end name_default = whitelist.wrapper_templates[template_name][vol][1]; -- get the default names date_default = whitelist.wrapper_templates[template_name][vol][2]; -- get the default date end if 'harv' == ref or not ref then -- |ref=harv specified or |ref= missing or empty anchor_id = names_get (params, aliases_contributor) or -- get contributor, author, or editor names names_get (params, aliases_author) or vnames_get (params, 'vauthors') or -- |vauthors= names_get (params, aliases_editor) or vnames_get (params, 'veditors') or -- |veditors= name_default; -- default names from whitelist -- whitelist.wrapper_templates[template_name][1]; -- default names from whitelist if '' == date then -- if date not provided in the template date = date_default; -- use the default date from whitelist end if anchor_id then -- if names were gotten anchor_id = 'CITEREF' .. anchor_id .. date; end elseif ref:match ('%b{}') then -- ref holds a template anchor_id = sfnref_get (ref); -- returns content of {{sfnref}} or {{harvid}}; nil else elseif 'none' == ref then -- |ref=none return nil; -- anchor id expicitly suppressed else anchor_id = ref; -- |ref=<text> may match an anchor id override value in {{harv}} template |ref= parameter end return anchor_id; -- anchor_id text; nil else end --[[--------------------------< A N C H O R _ I D _ M A K E _ C S 1 2 >---------------------------------------- for cs1|2 template and cs1-like templates inspect |ref= to decide what to do: |ref= - empty or missing: get names and date from template parameters; all cs1|2 create CITEREF anchor IDs |ref=harv - get names and date from template parameters |ref={{SfnRef|name|name|name|name|year}} - assemble an anchor id from {{sfnref}} positional parameters |ref={{Harvid|name|name|name|name|year}} - assemble an anchor id from {{harvid}} positional parameters |ref=none - skip; do nothing because an anchor id intentionally suppressed; TODO: keep with a type code of '0'? |ref=<text> - save param value because may match an anchor id override value in {{harv}} template |ref= parameter or {{harvc}} |id= parameter ]] local function anchor_id_make_cs12 (template) local ref; -- content of |ref= local template_name; -- name of the template local anchor_id; -- the assembled anchor id from this template local date; local params = {}; -- table of template parameters template_name = template_name_get (template); -- get first char uppercase trimmed template name; ignore subpages ~/new, ~/sandbox if not template_name or template_skip[template_name] then return nil; -- could not extract template name from (possibly corrupted) template (extraneous opening { in the template will cause this) end if redirects_patent[template_name] then date = date_get (template, alias_patterns_patent_date); -- get date; done here because might be in {{date}} else date = date_get (template, alias_patterns_date); end ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}} because we will strip templates from the cs1|2 template if not ref then if template:match ('|%s*ref%s*=([^|}]+)') then -- |ref={{template}} not found; if there is a |ref= param with an assigned value ref = template:match ('|%s*ref%s*=([^|}]+)'); -- get the value; whitespace is a 'value' if ref then -- nil when |ref=|... or when |ref=}} (no spaces between assignment operator and pipe or closing brace) ref = mw.text.trim (ref); -- something, could be just whitespace, so trim leading / trailing whitespace if '' == ref then -- trimming a string of whitespace makes an empty string ref = nil; -- make empty ref same as missing ref end end end end template_params_get (template, params); -- build a table of template parameters and their values if not ref then -- |ref= not set, might be cite LSA which doesn't support |ref= if 'cite lsa' == template_name then return 'CITEREF' .. (params.last or '') .. (params.year or ''); -- cite LSA always creates an anchor id using only |last= and |year= (no aliases) end end if 'harv' == ref or not ref then -- |ref=harv specified or |ref= missing or empty if redirects_patent[template_name] then -- if this is a cite patent template anchor_id = names_get (params, aliases_inventor); -- inventor names only else -- cs1|2 template anchor_id = names_get (params, aliases_contributor) or -- get contributor, author, or editor names names_get (params, aliases_author) or vnames_get (params, 'vauthors') or -- |vauthors= names_get (params, aliases_editor) or vnames_get (params, 'veditors'); -- |veditors= end if anchor_id then -- if names were gotten anchor_id = 'CITEREF' .. anchor_id .. date; end elseif ref:match ('%b{}') then -- ref holds a template anchor_id = sfnref_get (ref); -- returns content of {{sfnref}} or {{harvid}}; nil else elseif 'none' == ref and not redirects_patent[template_name] then -- |ref=none; not supported by cite patent return nil; -- anchor id expicitly suppressed else anchor_id = ref; -- |ref=<text> may match an anchor id override value in {{harv}} template |ref= parameter end return anchor_id; -- anchor_id text; nil else end --[[--------------------------< L I S T _ A D D >-------------------------------------------------------------- adds an <item> to <list> table; for anchor IDs, the boolean <encode> argument must be set true; no return value ]] local function list_add (item, list, encode) if item then -- if there was an item if encode then -- for anchor IDs ... item = mw.uri.anchorEncode (item); -- encode to remove wikimarkup, convert spaces to underscores etc end if not list[item] then -- if not already saved list[item] = 1; -- save it else -- here when this item already saved list[item] = list[item] + 1; -- to indicate that there are multiple items end end end --[[--------------------------< A N C H O R _ I D _ M A K E _ A N C H O R >------------------------------------ make anchor IDs from {{anchor}}; there may be more than one because {{anchor}} is not limited to the number of anchors it may hold. ]] local function anchor_id_make_anchor (template, anchor_id_list) template = template:gsub ('^{{[^|]+|', ''):gsub ('}}$', '', 1); -- remove outer {{ and }} and template name template = wikilink_strip (template); -- strip any wikilink markup (there shouldn't be any but just in case) local params = {}; local anchor_id; for param in template:gmatch ('%b{}') do -- loop through the template; remove and save templates (presumed to be sfnref or harvid) table.insert (params, param); -- save it template = template:gsub ('%b{}', '', 1); -- remove it from source template end for _, t in ipairs (params) do -- spin through the templates in params anchor_id = sfnref_get (t); -- attempt to decode {{sfnref}} and {{harvid}} if anchor_id then -- nil when not {{sfnref}} or {{harvid}} list_add (anchor_id, anchor_id_list, true); -- add anchor ID to the list end end template = template:gsub ('|%s*|', '|'); -- when pipe follows pipe with or without white space, remove extraneous pipe template = template:gsub ('^|', ''):gsub('|$', ''); -- remove extraneous leading and trailing pipes params = mw.text.split (template, '%s*|%s*'); -- split at the pipe and remove extraneous space characters for _, t in ipairs (params) do -- spin through the anchor IDs anchor_id = mw.text.trim (t); -- trim white space if '' ~= anchor_id then -- should always have something list_add (anchor_id, anchor_id_list, true); -- add anchor ID to the list end end end --[[--------------------------< T E M P L A T E _ L I S T _ A D D >-------------------------------------------- makes a list of templates use in the article. ]] local function template_list_add (template) local template = template:match ('{{%s*(.-)[|}]'); -- keep the case of the template - this is different from template_name_get() if template and not template:match ('^#') then -- found a template or magic word; ignore magic words template=mw.text.trim (template); -- trim whitespace template = Lang_obj:ucfirst (template); -- first character in template name must be uppercase (same as canonical template name) TODO: better way to do this? list_add (template, template_list); -- add to list with (unused) tally end end --[[--------------------------< A N C H O R _ I D _ L I S T _ M A K E >---------------------------------------- makes a list of anchor ids from cs1|2, cs1|2-like, vcite xxx, harvc, anchor, wikicite templates Because cs1|2 wrapper templates can, and often do, hide the author and date parameters inside the wrapper, these parameters are not available in the article's wikisource so {{harv}}, {{sfn}}, and {{harvc}} templates that link correctly to those wrapper templates will incorrectly show error messages. Use |ignore-err=yes in the {{harv}}, {{sfn}}, and {{harvc}} templates to supress the error message. creates a list of templates used in the article for use with the whitelist creates a list of article-local whitelisted anchor IDs from {{sfn whitelist}} ]] local function anchor_id_list_make () article_content_get (); -- attempt to get this article's content if '' == Article_content then -- when there is no article content return ''; -- no point in continuing end local template; -- place to hold the template that we found local template_name; local anchor_id; -- place to hold an anchor id as it is extracted / decoded local find_pattern = '%f[{]{{[^{]'; local tstart, tend = Article_content:find (find_pattern); -- find the first template; do not find template variables: {{{template var|}}} while tstart do template = Article_content:match ('%b{}', tstart); -- get the whole template if not template then break; -- template is nil for some reason (last template missing closing }} for example) so declare ourselves done end template_name = template_name_get (template); -- get first char uppercase trimmed template name; ignore subpages ~/new, ~/sandbox template_list_add (template); -- add this template's name to the list if data.known_templates_cs12 [template_name] then anchor_id = anchor_id_make_cs12 (template); -- extract an anchor id from this template list_add (anchor_id, anchor_id_list, true) elseif data.known_templates_vcite [template_name] then local ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}} because we will strip templates from the vcite template if ref then -- |ref={{template}} anchor_id = sfnref_get (ref); -- returns content of {{sfnref}} or {{harvid}}; nil else list_add (anchor_id, anchor_id_list, true); else local params = {}; template_params_get (template, params); -- build a table of template parameters and their values anchor_id = params['ref']; -- when both set, vcite uses value from |ref= if not anchor_id and params['harvid'] then anchor_id = 'CITEREF' .. params['harvid']; -- in vcite, |harvid= auto-adds 'CITEREF' prefix to the value in |harvid= end list_add (anchor_id, anchor_id_list, true); end elseif data.known_templates_harvc [template_name] then anchor_id = anchor_id_make_harvc (template); -- extract an anchor id from this template list_add (anchor_id, anchor_id_list, true); elseif data.known_templates_wikicite [template_name] then local ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}} if ref then anchor_id = sfnref_get (ref); elseif template:match ('|%s*ref%s*=([^|}]+)') then anchor_id = template:match ('|%s*ref%s*=([^|}]+)'); -- plain-text elseif template:match ('|%s*id%s*=%s*(%b{})') then ref = template:match ('|%s*id%s*=%s*(%b{})'); anchor_id = 'Reference-' .. sfnref_get (ref); elseif template:match ('|%s*id%s*=([^|}]+)') then anchor_id = 'Reference-' .. template:match ('|%s*id%s*=([^|}]+)'); -- plain-text else anchor_id = nil; -- no matches, ensure that anchor_id has no value end if anchor_id then list_add (anchor_id, anchor_id_list, true); end elseif data.known_templates_anchor [template_name] then anchor_id_make_anchor (template, anchor_id_list); -- extract anchor ids from this template if any elseif data.known_templates_sfn_whitelist [template_name] then template = template:gsub ('^{{[^|]+|', ''):gsub ('}}$', '', 1); -- remove outer {{ and }} and template name template = mw.text.trim (template, '%s|'); -- trim leading trailing white space and pipes template = mw.text.split (template, '%s*|%s*'); -- make a table of the template's parameters for _, anchor_id in ipairs (template) do -- spin through this template's parameter if '' ~= anchor_id and not article_whitelist[anchor_id] then anchor_id = mw.uri.anchorEncode (anchor_id) article_whitelist[anchor_id] = 1; -- add to the whitelist end end elseif template_name and whitelist.wrapper_templates[template_name] then anchor_id = anchor_id_make_wrapper (template); -- extract an anchor id from this template if possible list_add (anchor_id, anchor_id_list, true); elseif template_name and template_name:match ('^Cit[ea]') then -- not known, not known wrapper; last gasp, try as cs1-like anchor_id = anchor_id_make_cs12 (template); -- extract an anchor id from this template if possible list_add (anchor_id, anchor_id_list, true); end tstart, tend = Article_content:find (find_pattern, tend); -- search for another template; begin at end of last search end mw.logObject (anchor_id_list, 'anchor_id_list'); mw.logObject (template_list, 'template_list'); mw.logObject (article_whitelist, 'article_whitelist'); return anchor_id_list; end --[[--------------------------< E X P O R T E D _ T A B L E S >------------------------------------------------ ]] return { anchor_id_list = anchor_id_list_make(), -- table of anchor ids available in this article article_whitelist = article_whitelist, -- table of anchor ids with false-positive error message to be suppressed template_list = template_list, -- table of templates used in this article } 9cf1091b65b65bfb32bb0aa2b73bb581d19e99f1 Module:Navbox/styles.css 828 115 245 2021-12-21T22:10:10Z Canopus >Izno 0 remove qualifications on th - this will remove styling from "hand-crafted" navboxes, but there's no other elegant way to deal with it. see talk page text text/plain /* {{pp|small=y}} */ .navbox { box-sizing: border-box; border: 1px solid #a2a9b1; width: 100%; clear: both; font-size: 88%; text-align: center; padding: 1px; margin: 1em auto 0; /* Prevent preceding content from clinging to navboxes */ } .navbox .navbox { margin-top: 0; /* No top margin for nested navboxes */ } .navbox + .navbox, /* TODO: remove first line after transclusions have updated */ .navbox + .navbox-styles + .navbox { margin-top: -1px; /* Single pixel border between adjacent navboxes */ } .navbox-inner, .navbox-subgroup { width: 100%; } .navbox-group, .navbox-title, .navbox-abovebelow { padding: 0.25em 1em; line-height: 1.5em; text-align: center; } .navbox-group { white-space: nowrap; /* @noflip */ text-align: right; } .navbox, .navbox-subgroup { background-color: #fdfdfd; } .navbox-list { line-height: 1.5em; border-color: #fdfdfd; /* Must match background color */ } .navbox-list-with-group { text-align: left; border-left-width: 2px; border-left-style: solid; } /* cell spacing for navbox cells */ /* Borders above 2nd, 3rd, etc. rows */ /* TODO: figure out how to replace tr as structure; * with div structure it should be just a matter of first-child */ tr + tr > .navbox-abovebelow, tr + tr > .navbox-group, tr + tr > .navbox-image, tr + tr > .navbox-list { border-top: 2px solid #fdfdfd; /* Must match background color */ } .navbox-title { background-color: #ccf; /* Level 1 color */ } .navbox-abovebelow, .navbox-group, .navbox-subgroup .navbox-title { background-color: #ddf; /* Level 2 color */ } .navbox-subgroup .navbox-group, .navbox-subgroup .navbox-abovebelow { background-color: #e6e6ff; /* Level 3 color */ } .navbox-even { background-color: #f7f7f7; } .navbox-odd { background-color: transparent; } /* TODO: figure out how to remove reliance on td as structure */ .navbox .hlist td dl, .navbox .hlist td ol, .navbox .hlist td ul, .navbox td.hlist dl, .navbox td.hlist ol, .navbox td.hlist ul { padding: 0.125em 0; } .navbox .navbar { display: block; font-size: 100%; } .navbox-title .navbar { /* @noflip */ float: left; /* @noflip */ text-align: left; /* @noflip */ margin-right: 0.5em; } e80b0d7a5770e6e105dab832deb6c37a5245ebc6 Template:Other uses 10 99 213 2021-12-26T18:42:03Z Canopus >Nihiltres 0 Removed categorization system as redundant wikitext text/x-wiki {{#invoke:other uses|otheruses}}<noinclude>{{documentation}}</noinclude> 3bd6c67c92b11a14d2e58145b096152fbc066580 Module:Hatnote list 828 109 233 2021-12-26T20:05:24Z Canopus >Nihiltres 0 Undid revision 1062166786 by [[Special:Contributions/Matthiaspaul|Matthiaspaul]] ([[User talk:Matthiaspaul|talk]]); should be fixed now, and if not, please ping me with examples as I couldn't reproduce the original error Scribunto text/plain -------------------------------------------------------------------------------- -- Module:Hatnote list -- -- -- -- This module produces and formats lists for use in hatnotes. In particular, -- -- it implements the for-see list, i.e. lists of "For X, see Y" statements, -- -- as used in {{about}}, {{redirect}}, and their variants. Also introduced -- -- are andList & orList helpers for formatting lists with those conjunctions. -- -------------------------------------------------------------------------------- local mArguments --initialize lazily local mFormatLink = require('Module:Format link') local mHatnote = require('Module:Hatnote') local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local p = {} -------------------------------------------------------------------------------- -- List stringification helper functions -- -- These functions are used for stringifying lists, usually page lists inside -- the "Y" portion of "For X, see Y" for-see items. -------------------------------------------------------------------------------- --default options table used across the list stringification functions local stringifyListDefaultOptions = { conjunction = "and", separator = ",", altSeparator = ";", space = " ", formatted = false } --Searches display text only local function searchDisp(haystack, needle) return string.find( string.sub(haystack, (string.find(haystack, '|') or 0) + 1), needle ) end -- Stringifies a list generically; probably shouldn't be used directly local function stringifyList(list, options) -- Type-checks, defaults, and a shortcut checkType("stringifyList", 1, list, "table") if #list == 0 then return nil end checkType("stringifyList", 2, options, "table", true) options = options or {} for k, v in pairs(stringifyListDefaultOptions) do if options[k] == nil then options[k] = v end end local s = options.space -- Format the list if requested if options.formatted then list = mFormatLink.formatPages( {categorizeMissing = mHatnote.missingTargetCat}, list ) end -- Set the separator; if any item contains it, use the alternate separator local separator = options.separator for k, v in pairs(list) do if searchDisp(v, separator) then separator = options.altSeparator break end end -- Set the conjunction, apply Oxford comma, and force a comma if #1 has "§" local conjunction = s .. options.conjunction .. s if #list == 2 and searchDisp(list[1], "§") or #list > 2 then conjunction = separator .. conjunction end -- Return the formatted string return mw.text.listToText(list, separator .. s, conjunction) end --DRY function function p.conjList (conj, list, fmt) return stringifyList(list, {conjunction = conj, formatted = fmt}) end -- Stringifies lists with "and" or "or" function p.andList (...) return p.conjList("and", ...) end function p.orList (...) return p.conjList("or", ...) end -------------------------------------------------------------------------------- -- For see -- -- Makes a "For X, see [[Y]]." list from raw parameters. Intended for the -- {{about}} and {{redirect}} templates and their variants. -------------------------------------------------------------------------------- --default options table used across the forSee family of functions local forSeeDefaultOptions = { andKeyword = 'and', title = mw.title.getCurrentTitle().text, otherText = 'other uses', forSeeForm = 'For %s, see %s.', } --Collapses duplicate punctuation local function punctuationCollapse (text) local replacements = { ["%.%.$"] = ".", ["%?%.$"] = "?", ["%!%.$"] = "!", ["%.%]%]%.$"] = ".]]", ["%?%]%]%.$"] = "?]]", ["%!%]%]%.$"] = "!]]" } for k, v in pairs(replacements) do text = string.gsub(text, k, v) end return text end -- Structures arguments into a table for stringification, & options function p.forSeeArgsToTable (args, from, options) -- Type-checks and defaults checkType("forSeeArgsToTable", 1, args, 'table') checkType("forSeeArgsToTable", 2, from, 'number', true) from = from or 1 checkType("forSeeArgsToTable", 3, options, 'table', true) options = options or {} for k, v in pairs(forSeeDefaultOptions) do if options[k] == nil then options[k] = v end end -- maxArg's gotten manually because getArgs() and table.maxn aren't friends local maxArg = 0 for k, v in pairs(args) do if type(k) == 'number' and k > maxArg then maxArg = k end end -- Structure the data out from the parameter list: -- * forTable is the wrapper table, with forRow rows -- * Rows are tables of a "use" string & a "pages" table of pagename strings -- * Blanks are left empty for defaulting elsewhere, but can terminate list local forTable = {} local i = from local terminated = false -- If there is extra text, and no arguments are given, give nil value -- to not produce default of "For other uses, see foo (disambiguation)" if options.extratext and i > maxArg then return nil end -- Loop to generate rows repeat -- New empty row local forRow = {} -- On blank use, assume list's ended & break at end of this loop forRow.use = args[i] if not args[i] then terminated = true end -- New empty list of pages forRow.pages = {} -- Insert first pages item if present table.insert(forRow.pages, args[i + 1]) -- If the param after next is "and", do inner loop to collect params -- until the "and"'s stop. Blanks are ignored: "1|and||and|3" → {1, 3} while args[i + 2] == options.andKeyword do if args[i + 3] then table.insert(forRow.pages, args[i + 3]) end -- Increment to next "and" i = i + 2 end -- Increment to next use i = i + 2 -- Append the row table.insert(forTable, forRow) until terminated or i > maxArg return forTable end -- Stringifies a table as formatted by forSeeArgsToTable function p.forSeeTableToString (forSeeTable, options) -- Type-checks and defaults checkType("forSeeTableToString", 1, forSeeTable, "table", true) checkType("forSeeTableToString", 2, options, "table", true) options = options or {} for k, v in pairs(forSeeDefaultOptions) do if options[k] == nil then options[k] = v end end -- Stringify each for-see item into a list local strList = {} if forSeeTable then for k, v in pairs(forSeeTable) do local useStr = v.use or options.otherText local pagesStr = p.andList(v.pages, true) or mFormatLink._formatLink{ categorizeMissing = mHatnote.missingTargetCat, link = mHatnote.disambiguate(options.title) } local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr) forSeeStr = punctuationCollapse(forSeeStr) table.insert(strList, forSeeStr) end end if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..'.')) end -- Return the concatenated list return table.concat(strList, ' ') end -- Produces a "For X, see [[Y]]" string from arguments. Expects index gaps -- but not blank/whitespace values. Ignores named args and args < "from". function p._forSee (args, from, options) local forSeeTable = p.forSeeArgsToTable(args, from, options) return p.forSeeTableToString(forSeeTable, options) end -- As _forSee, but uses the frame. function p.forSee (frame, from, options) mArguments = require('Module:Arguments') return p._forSee(mArguments.getArgs(frame), from, options) end return p d0828422b1aa0d0d0092d699d059c9e882260398 Template:Order of magnitude 10 137 289 2022-01-02T09:08:29Z Canopus >Dinoguy1000 0 fix "|=foo" bug wikitext text/x-wiki <includeonly>{{safesubst:<noinclude/>#ifexpr:{{{1|0}}}=0 |{{safesubst:<noinclude/>#ifexpr:abs{{{1|0}}}1=1 |0 |{{safesubst:<noinclude/>#expr:floor((ln(abs{{{1}}}1)/ln10)+1)}} }} |{{safesubst:<noinclude/>#expr:floor((ln(abs({{{1|0}}}) )/ln 10)+1E((abs{{{1|0}}}>1E100 or abs{{{1|0}}}<1E-100)-14))}} }}</includeonly><noinclude> {{documentation}} </noinclude> cede5694e8ebb404ecdd17ae1f8e1c5d19562728 Module:Navbar/styles.css 828 112 239 2022-01-03T23:12:15Z Canopus >Izno 0 navbar styles that were moved to parent templates text text/plain /* {{pp|small=yes}} */ .navbar { display: inline; font-size: 88%; font-weight: normal; } .navbar-collapse { float: left; text-align: left; } .navbar-boxtext { word-spacing: 0; } .navbar ul { display: inline-block; white-space: nowrap; line-height: inherit; } .navbar-brackets::before { margin-right: -0.125em; content: '[ '; } .navbar-brackets::after { margin-left: -0.125em; content: ' ]'; } .navbar li { word-spacing: -0.125em; } .navbar a > span, .navbar a > abbr { text-decoration: inherit; } .navbar-mini abbr { font-variant: small-caps; border-bottom: none; text-decoration: none; cursor: inherit; } .navbar-ct-full { font-size: 114%; margin: 0 7em; } .navbar-ct-mini { font-size: 114%; margin: 0 4em; } 9d4056f949b4f0b159e3d40dfb1a5f01e72f9571 Module:Navbox 828 113 241 2022-01-07T21:39:23Z Canopus >Izno 0 remove titlegroup per templatestyles section on talk page Scribunto text/plain local p = {} local navbar = require('Module:Navbar')._navbar local cfg = mw.loadData('Module:Navbox/configuration') local getArgs -- lazily initialized local args local format = string.format local function striped(wikitext, border) -- Return wikitext with markers replaced for odd/even striping. -- Child (subgroup) navboxes are flagged with a category that is removed -- by parent navboxes. The result is that the category shows all pages -- where a child navbox is not contained in a parent navbox. local orphanCat = cfg.category.orphan if border == cfg.keyword.border_subgroup and args[cfg.arg.orphan] ~= cfg.keyword.orphan_yes then -- No change; striping occurs in outermost navbox. return wikitext .. orphanCat end local first, second = cfg.class.navbox_odd_part, cfg.class.navbox_even_part if args[cfg.arg.evenodd] then if args[cfg.arg.evenodd] == cfg.keyword.evenodd_swap then first, second = second, first else first = args[cfg.arg.evenodd] second = first end end local changer if first == second then changer = first else local index = 0 changer = function (code) if code == '0' then -- Current occurrence is for a group before a nested table. -- Set it to first as a valid although pointless class. -- The next occurrence will be the first row after a title -- in a subgroup and will also be first. index = 0 return first end index = index + 1 return index % 2 == 1 and first or second end end local regex = orphanCat:gsub('([%[%]])', '%%%1') return (wikitext:gsub(regex, ''):gsub(cfg.marker.regex, changer)) -- () omits gsub count end local function processItem(item, nowrapitems) if item:sub(1, 2) == '{|' then -- Applying nowrap to lines in a table does not make sense. -- Add newlines to compensate for trim of x in |parm=x in a template. return '\n' .. item ..'\n' end if nowrapitems == cfg.keyword.nowrapitems_yes then local lines = {} for line in (item .. '\n'):gmatch('([^\n]*)\n') do local prefix, content = line:match('^([*:;#]+)%s*(.*)') if prefix and not content:match(cfg.pattern.nowrap) then line = format(cfg.nowrap_item, prefix, content) end table.insert(lines, line) end item = table.concat(lines, '\n') end if item:match('^[*:;#]') then return '\n' .. item ..'\n' end return item end -- we will want this later when we want to add tstyles for hlist/plainlist local function has_navbar() return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain and ( args[cfg.arg.name] or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '') ~= cfg.pattern.navbox ) end local function renderNavBar(titleCell) if has_navbar() then titleCell:wikitext(navbar{ [cfg.navbar.name] = args[cfg.arg.name], [cfg.navbar.mini] = 1, [cfg.navbar.fontstyle] = (args[cfg.arg.basestyle] or '') .. ';' .. (args[cfg.arg.titlestyle] or '') .. ';background:none transparent;border:none;box-shadow:none;padding:0;' }) end end local function renderTitleRow(tbl) if not args[cfg.arg.title] then return end local titleRow = tbl:tag('tr') local titleCell = titleRow:tag('th'):attr('scope', 'col') local titleColspan = 2 if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end if args[cfg.arg.image] then titleColspan = titleColspan + 1 end titleCell :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.titlestyle]) :addClass(cfg.class.navbox_title) :attr('colspan', titleColspan) renderNavBar(titleCell) titleCell :tag('div') -- id for aria-labelledby attribute :attr('id', mw.uri.anchorEncode(args[cfg.arg.title])) :addClass(args[cfg.arg.titleclass]) :css('font-size', '114%') :css('margin', '0 4em') :wikitext(processItem(args[cfg.arg.title])) end local function getAboveBelowColspan() local ret = 2 if args[cfg.arg.imageleft] then ret = ret + 1 end if args[cfg.arg.image] then ret = ret + 1 end return ret end local function renderAboveRow(tbl) if not args[cfg.arg.above] then return end tbl:tag('tr') :tag('td') :addClass(cfg.class.navbox_abovebelow) :addClass(args[cfg.arg.aboveclass]) :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.abovestyle]) :attr('colspan', getAboveBelowColspan()) :tag('div') -- id for aria-labelledby attribute, if no title :attr('id', args[cfg.arg.title] and nil or mw.uri.anchorEncode(args[cfg.arg.above])) :wikitext(processItem(args[cfg.arg.above], args[cfg.arg.nowrapitems])) end local function renderBelowRow(tbl) if not args[cfg.arg.below] then return end tbl:tag('tr') :tag('td') :addClass(cfg.class.navbox_abovebelow) :addClass(args[cfg.arg.belowclass]) :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.belowstyle]) :attr('colspan', getAboveBelowColspan()) :tag('div') :wikitext(processItem(args[cfg.arg.below], args[cfg.arg.nowrapitems])) end local function renderListRow(tbl, index, listnum, listnums_size) local row = tbl:tag('tr') if index == 1 and args[cfg.arg.imageleft] then row :tag('td') :addClass(cfg.class.noviewer) :addClass(cfg.class.navbox_image) :addClass(args[cfg.arg.imageclass]) :css('width', '1px') -- Minimize width :css('padding', '0 2px 0 0') :cssText(args[cfg.arg.imageleftstyle]) :attr('rowspan', listnums_size) :tag('div') :wikitext(processItem(args[cfg.arg.imageleft])) end local group_and_num = format(cfg.arg.group_and_num, listnum) local groupstyle_and_num = format(cfg.arg.groupstyle_and_num, listnum) if args[group_and_num] then local groupCell = row:tag('th') -- id for aria-labelledby attribute, if lone group with no title or above if listnum == 1 and not (args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group2]) then groupCell :attr('id', mw.uri.anchorEncode(args[cfg.arg.group1])) end groupCell :attr('scope', 'row') :addClass(cfg.class.navbox_group) :addClass(args[cfg.arg.groupclass]) :cssText(args[cfg.arg.basestyle]) -- If groupwidth not specified, minimize width :css('width', args[cfg.arg.groupwidth] or '1%') groupCell :cssText(args[cfg.arg.groupstyle]) :cssText(args[groupstyle_and_num]) :wikitext(args[group_and_num]) end local listCell = row:tag('td') if args[group_and_num] then listCell :addClass(cfg.class.navbox_list_with_group) else listCell:attr('colspan', 2) end if not args[cfg.arg.groupwidth] then listCell:css('width', '100%') end local rowstyle -- usually nil so cssText(rowstyle) usually adds nothing if index % 2 == 1 then rowstyle = args[cfg.arg.oddstyle] else rowstyle = args[cfg.arg.evenstyle] end local list_and_num = format(cfg.arg.list_and_num, listnum) local listText = args[list_and_num] local oddEven = cfg.marker.oddeven if listText:sub(1, 12) == '</div><table' then -- Assume list text is for a subgroup navbox so no automatic striping for this row. oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part end local liststyle_and_num = format(cfg.arg.liststyle_and_num, listnum) local listclass_and_num = format(cfg.arg.listclass_and_num, listnum) listCell :css('padding', '0') :cssText(args[cfg.arg.liststyle]) :cssText(rowstyle) :cssText(args[liststyle_and_num]) :addClass(cfg.class.navbox_list) :addClass(cfg.class.navbox_part .. oddEven) :addClass(args[cfg.arg.listclass]) :addClass(args[listclass_and_num]) :tag('div') :css('padding', (index == 1 and args[cfg.arg.list1padding]) or args[cfg.arg.listpadding] or '0 0.25em' ) :wikitext(processItem(listText, args[cfg.arg.nowrapitems])) if index == 1 and args[cfg.arg.image] then row :tag('td') :addClass(cfg.class.noviewer) :addClass(cfg.class.navbox_image) :addClass(args[cfg.arg.imageclass]) :css('width', '1px') -- Minimize width :css('padding', '0 0 0 2px') :cssText(args[cfg.arg.imagestyle]) :attr('rowspan', listnums_size) :tag('div') :wikitext(processItem(args[cfg.arg.image])) end end -- uses this now to make the needHlistCategory correct -- to use later for when we add list styles via navbox local function has_list_class(htmlclass) local class_args = { -- rough order of probability of use cfg.arg.bodyclass, cfg.arg.listclass, cfg.arg.aboveclass, cfg.arg.belowclass, cfg.arg.titleclass, cfg.arg.navboxclass, cfg.arg.groupclass, cfg.arg.imageclass } local patterns = { '^' .. htmlclass .. '$', '%s' .. htmlclass .. '$', '^' .. htmlclass .. '%s', '%s' .. htmlclass .. '%s' } for _, arg in ipairs(class_args) do for _, pattern in ipairs(patterns) do if mw.ustring.find(args[arg] or '', pattern) then return true end end end return false end local function needsHorizontalLists(border) if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then return false end return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist) end local function hasBackgroundColors() for _, key in ipairs({cfg.arg.titlestyle, cfg.arg.groupstyle, cfg.arg.basestyle, cfg.arg.abovestyle, cfg.arg.belowstyle}) do if tostring(args[key]):find('background', 1, true) then return true end end return false end local function hasBorders() for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle, cfg.arg.abovestyle, cfg.arg.belowstyle}) do if tostring(args[key]):find('border', 1, true) then return true end end return false end local function isIllegible() local styleratio = require('Module:Color contrast')._styleratio for key, style in pairs(args) do if tostring(key):match(cfg.pattern.style) then if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then return true end end end return false end local function getTrackingCategories(border) local cats = {} if needsHorizontalLists(border) then table.insert(cats, cfg.category.horizontal_lists) end if hasBackgroundColors() then table.insert(cats, cfg.category.background_colors) end if isIllegible() then table.insert(cats, cfg.category.illegible) end if hasBorders() then table.insert(cats, cfg.category.borders) end return cats end local function renderTrackingCategories(builder, border) local title = mw.title.getCurrentTitle() if title.namespace ~= 10 then return end -- not in template space local subpage = title.subpageText if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox or subpage == cfg.keyword.subpage_testcases then return end for _, cat in ipairs(getTrackingCategories(border)) do builder:wikitext('[[Category:' .. cat .. ']]') end end local function renderMainTable(border, listnums) local tbl = mw.html.create('table') :addClass(cfg.class.nowraplinks) :addClass(args[cfg.arg.bodyclass]) local state = args[cfg.arg.state] if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then if state == cfg.keyword.state_collapsed then state = cfg.class.collapsed end tbl :addClass(cfg.class.collapsible) :addClass(state or cfg.class.autocollapse) end tbl:css('border-spacing', 0) if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then tbl :addClass(cfg.class.navbox_subgroup) :cssText(args[cfg.arg.bodystyle]) :cssText(args[cfg.arg.style]) else -- regular navbox - bodystyle and style will be applied to the wrapper table tbl :addClass(cfg.class.navbox_inner) :css('background', 'transparent') :css('color', 'inherit') end tbl:cssText(args[cfg.arg.innerstyle]) renderTitleRow(tbl) renderAboveRow(tbl) local listnums_size = #listnums for i, listnum in ipairs(listnums) do renderListRow(tbl, i, listnum, listnums_size) end renderBelowRow(tbl) return tbl end local function add_navbox_styles() local frame = mw.getCurrentFrame() -- This is a lambda so that it doesn't need the frame as a parameter local function add_user_styles(templatestyles) if templatestyles and templatestyles ~= '' then return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles } } end return '' end -- get templatestyles. load base from config so that Lua only needs to do -- the work once of parser tag expansion local base_templatestyles = cfg.templatestyles local templatestyles = add_user_styles(args[cfg.arg.templatestyles]) local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles]) -- The 'navbox-styles' div exists for two reasons: -- 1. To wrap the styles to work around T200206 more elegantly. Instead -- of combinatorial rules, this ends up being linear number of CSS rules. -- 2. To allow MobileFrontend to rip the styles out with 'nomobile' such that -- they are not dumped into the mobile view. return mw.html.create('div') :addClass(cfg.class.navbox_styles) :addClass(cfg.class.nomobile) :wikitext(base_templatestyles .. templatestyles .. child_templatestyles) :done() end function p._navbox(navboxArgs) args = navboxArgs local listnums = {} for k, _ in pairs(args) do if type(k) == 'string' then local listnum = k:match(cfg.pattern.listnum) if listnum then table.insert(listnums, tonumber(listnum)) end end end table.sort(listnums) local border = mw.text.trim(args[cfg.arg.border] or args[1] or '') if border == cfg.keyword.border_child then border = cfg.keyword.border_subgroup end -- render the main body of the navbox local tbl = renderMainTable(border, listnums) local res = mw.html.create() -- render the appropriate wrapper for the navbox, based on the border param if border == cfg.keyword.border_none then res:node(add_navbox_styles()) local nav = res:tag('div') :attr('role', 'navigation') :node(tbl) -- aria-labelledby title, otherwise above, otherwise lone group if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then nav:attr( 'aria-labelledby', mw.uri.anchorEncode( args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1] ) ) else nav:attr('aria-label', cfg.aria_label) end elseif border == cfg.keyword.border_subgroup then -- We assume that this navbox is being rendered in a list cell of a -- parent navbox, and is therefore inside a div with padding:0em 0.25em. -- We start with a </div> to avoid the padding being applied, and at the -- end add a <div> to balance out the parent's </div> res :wikitext('</div>') :node(tbl) :wikitext('<div>') else res:node(add_navbox_styles()) local nav = res:tag('div') :attr('role', 'navigation') :addClass(cfg.class.navbox) :addClass(args[cfg.arg.navboxclass]) :cssText(args[cfg.arg.bodystyle]) :cssText(args[cfg.arg.style]) :css('padding', '3px') :node(tbl) -- aria-labelledby title, otherwise above, otherwise lone group if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then nav:attr( 'aria-labelledby', mw.uri.anchorEncode(args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]) ) else nav:attr('aria-label', cfg.aria_label) end end if (args[cfg.arg.nocat] or cfg.keyword.nocat_false):lower() == cfg.keyword.nocat_false then renderTrackingCategories(res, border) end return striped(tostring(res), border) end function p.navbox(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end args = getArgs(frame, {wrappers = {cfg.pattern.navbox}}) -- Read the arguments in the order they'll be output in, to make references -- number in the right order. local _ _ = args[cfg.arg.title] _ = args[cfg.arg.above] -- Limit this to 20 as covering 'most' cases (that's a SWAG) and because -- iterator approach won't work here for i = 1, 20 do _ = args[format(cfg.arg.group_and_num, i)] _ = args[format(cfg.arg.list_and_num, i)] end _ = args[cfg.arg.below] return p._navbox(args) end return p 5bbd6589b208bd567b351b855083c132c16a0fb9 Module:Navbox/configuration 828 114 243 2022-01-07T21:39:52Z Canopus >Izno 0 remove titlegroup Scribunto text/plain return { aria_label = 'Navbox', nowrap_item = '%s<span class="nowrap">%s</span>', templatestyles = mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Module:Navbox/styles.css' } }, -- do not localize marker table marker = { oddeven = '\127_ODDEVEN_\127', restart = '\127_ODDEVEN0_\127', regex = '\127_ODDEVEN(%d?)_\127' }, category = { orphan = '[[Category:Navbox orphans]]', horizontal_lists = 'Navigational boxes without horizontal lists', background_colors = 'Navboxes using background colours', illegible = 'Potentially illegible navboxes', borders = 'Navboxes using borders', }, keyword = { border_subgroup = 'subgroup', border_child = 'child', border_none = 'none', evenodd_swap = 'swap', navbar_off = 'off', navbar_plain = 'plain', nocat_false = 'false', nowrapitems_yes = 'yes', orphan_yes = 'yes', state_collapsed = 'collapsed', state_off = 'off', state_plain = 'plain', subpage_doc = 'doc', subpage_sandbox = 'sandbox', subpage_testcases = 'testcases', tracking_no = 'no' }, class = { autocollapse = 'autocollapse', collapsible = 'mw-collapsible', collapsed = 'mw-collapsed', -- Warning navbox = 'navbox', -- WMF currently hides 'navbox' from mobile, -- so you probably shouldn't change the navbox class. navbox_abovebelow = 'navbox-abovebelow', navbox_group = 'navbox-group', navbox_image = 'navbox-image', navbox_inner = 'navbox-inner', navbox_list = 'navbox-list', navbox_list_with_group = 'navbox-list-with-group', navbox_part = 'navbox-', -- do not l10n navbox_styles = 'navbox-styles', navbox_subgroup = 'navbox-subgroup', navbox_title = 'navbox-title', -- l10n only if you change pattern.navbox_title below navbox_odd_part = 'odd', -- do not l10n navbox_even_part = 'even', -- do not l10n nomobile = 'nomobile', nowraplinks = 'nowraplinks', noviewer = 'noviewer' -- used to remove images from MediaViewer }, pattern = { listnum = '^list(%d+)$', sandbox = '/sandbox$', navbox = 'Template:Navbox', nowrap = '^<span class="nowrap">', style = 'style$', navbox_title = '<th[^>]*"navbox%-title"', hlist = 'hlist', plainlist = 'plainlist' }, arg = { above = 'above', aboveclass = 'aboveclass', abovestyle = 'abovestyle', basestyle = 'basestyle', bodyclass = 'bodyclass', bodystyle = 'bodystyle', border = 'border', below = 'below', belowclass = 'belowclass', belowstyle = 'belowstyle', evenodd = 'evenodd', evenstyle = 'evenstyle', group1 = 'group1', group2 = 'group2', group_and_num = 'group%d', groupstyle_and_num = 'group%dstyle', groupclass = 'groupclass', groupstyle = 'groupstyle', groupwidth = 'groupwidth', innerstyle = 'innerstyle', image = 'image', imageclass = 'imageclass', imageleft = 'imageleft', imageleftstyle = 'imageleftstyle', imagesetyle = 'imagestyle', list_and_num = 'list%d', listclass_and_num = 'list%dclass', liststyle_and_num = 'list%dstyle', list1padding = 'list1padding', listclass = 'listclass', listpadding = 'listpadding', liststyle = 'liststyle', name = 'name', navbar = 'navbar', navboxclass = 'navboxclass', nocat = 'nocat', nowrapitems = 'nowrapitems', oddstyle = 'oddstyle', orphan = 'orphan', state = 'state', style = 'style', templatestyles = 'templatestyles', child_templatestyles = 'child templatestyles', title = 'title', titleclass = 'titleclass', titlestyle = 'titlestyle', tracking = 'tracking' }, -- names of navbar arguments navbar = { name = 1, fontstyle = 'fontstyle', mini = 'mini' } } 4a1fb97efbf7aa8a852959457b43eab420073194 Module:Format link 828 106 227 2022-01-09T02:48:07Z Canopus >Hike395 0 incorrect entry point Scribunto text/plain -------------------------------------------------------------------------------- -- Format link -- -- Makes a wikilink from the given link and display values. Links are escaped -- with colons if necessary, and links to sections are detected and displayed -- with " § " as a separator rather than the standard MediaWiki "#". Used in -- the {{format link}} template. -------------------------------------------------------------------------------- local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg local mArguments -- lazily initialise [[Module:Arguments]] local mError -- lazily initialise [[Module:Error]] local yesno -- lazily initialise [[Module:Yesno]] local p = {} -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- local function getArgs(frame) -- Fetches the arguments from the parent frame. Whitespace is trimmed and -- blanks are removed. mArguments = require('Module:Arguments') return mArguments.getArgs(frame, {parentOnly = true}) end local function removeInitialColon(s) -- Removes the initial colon from a string, if present. return s:match('^:?(.*)') end local function maybeItalicize(s, shouldItalicize) -- Italicize s if s is a string and the shouldItalicize parameter is true. if s and shouldItalicize then return '<i>' .. s .. '</i>' else return s end end local function parseLink(link) -- Parse a link and return a table with the link's components. -- These components are: -- - link: the link, stripped of any initial colon (always present) -- - page: the page name (always present) -- - section: the page name (may be nil) -- - display: the display text, if manually entered after a pipe (may be nil) link = removeInitialColon(link) -- Find whether a faux display value has been added with the {{!}} magic -- word. local prePipe, display = link:match('^(.-)|(.*)$') link = prePipe or link -- Find the page, if it exists. -- For links like [[#Bar]], the page will be nil. local preHash, postHash = link:match('^(.-)#(.*)$') local page if not preHash then -- We have a link like [[Foo]]. page = link elseif preHash ~= '' then -- We have a link like [[Foo#Bar]]. page = preHash end -- Find the section, if it exists. local section if postHash and postHash ~= '' then section = postHash end return { link = link, page = page, section = section, display = display, } end local function formatDisplay(parsed, options) -- Formats a display string based on a parsed link table (matching the -- output of parseLink) and an options table (matching the input options for -- _formatLink). local page = maybeItalicize(parsed.page, options.italicizePage) local section = maybeItalicize(parsed.section, options.italicizeSection) if (not section) then return page elseif (not page) then return mw.ustring.format('§&nbsp;%s', section) else return mw.ustring.format('%s §&nbsp;%s', page, section) end end local function missingArgError(target) mError = require('Module:Error') return mError.error{message = 'Error: no link or target specified! ([[' .. target .. '#Errors|help]])' } end -------------------------------------------------------------------------------- -- Main functions -------------------------------------------------------------------------------- function p.formatLink(frame) -- The formatLink export function, for use in templates. yesno = require('Module:Yesno') local args = getArgs(frame) local link = args[1] or args.link local target = args[3] or args.target if not (link or target) then return missingArgError('Template:Format link') end return p._formatLink{ link = link, display = args[2] or args.display, target = target, italicizePage = yesno(args.italicizepage), italicizeSection = yesno(args.italicizesection), categorizeMissing = args.categorizemissing } end function p._formatLink(options) -- The formatLink export function, for use in modules. checkType('_formatLink', 1, options, 'table') local function check(key, expectedType) --for brevity checkTypeForNamedArg( '_formatLink', key, options[key], expectedType or 'string', true ) end check('link') check('display') check('target') check('italicizePage', 'boolean') check('italicizeSection', 'boolean') check('categorizeMissing') -- Normalize link and target and check that at least one is present if options.link == '' then options.link = nil end if options.target == '' then options.target = nil end if not (options.link or options.target) then return missingArgError('Module:Format link') end local parsed = parseLink(options.link) local display = options.display or parsed.display local catMissing = options.categorizeMissing local category = '' -- Find the display text if not display then display = formatDisplay(parsed, options) end -- Handle the target option if present if options.target then local parsedTarget = parseLink(options.target) parsed.link = parsedTarget.link parsed.page = parsedTarget.page end -- Test if page exists if a diagnostic category is specified if catMissing and (mw.ustring.len(catMissing) > 0) then local title = nil if parsed.page then title = mw.title.new(parsed.page) end if title and (not title.isExternal) and (not title.exists) then category = mw.ustring.format('[[Category:%s]]', catMissing) end end -- Format the result as a link if parsed.link == display then return mw.ustring.format('[[:%s]]%s', parsed.link, category) else return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category) end end -------------------------------------------------------------------------------- -- Derived convenience functions -------------------------------------------------------------------------------- function p.formatPages(options, pages) -- Formats an array of pages using formatLink and the given options table, -- and returns it as an array. Nil values are not allowed. local ret = {} for i, page in ipairs(pages) do ret[i] = p._formatLink{ link = page, categorizeMissing = options.categorizeMissing, italicizePage = options.italicizePage, italicizeSection = options.italicizeSection } end return ret end return p b1a3177dc2ec780dc0a9720bfb64058aed46db95 Module:Citation/CS1/styles.css 828 57 129 2022-01-22T14:11:09Z Canopus >Trappist the monk 0 update per [[Wikipedia:Village_pump_(proposals)#rfc:_shall_we_update_cs1/2?|RfC]]; text text/plain /* Protection icon the following line controls the page-protection icon in the upper right corner it must remain within this comment {{sandbox other||{{pp-template}}}} */ /* Overrides Some wikis do not override user agent default styles for HTML <cite> and <q>, unlike en.wp. On en.wp, keep these the same as [[MediaWiki:Common.css]]. The word-wrap and :target styles were moved here from Common.css. On en.wp, keep these the same as [[Template:Citation/styles.css]]. */ cite.citation { font-style: inherit; /* Remove italics for <cite> */ /* Break long urls, etc., rather than overflowing box */ word-wrap: break-word; } .citation q { quotes: '"' '"' "'" "'"; /* Straight quote marks for <q> */ } /* Highlight linked elements (such as clicked references) in blue */ .citation:target { /* ignore the linter - all browsers of interest implement this */ background-color: rgba(0, 127, 255, 0.133); } /* ID and URL access Both core and Common.css have selector .mw-parser-output a[href$=".pdf"].external for PDF pages. All TemplateStyles pages are hoisted to .mw-parser-output. We need to have specificity equal to a[href$=".pdf"].external for locks to override PDF icon. That's essentially 2 classes and 1 element. the .id-lock-... selectors are for use by non-citation templates like {{Catalog lookup link}} which do not have to handle PDF links */ .id-lock-free a, .citation .cs1-lock-free a { background: linear-gradient(transparent, transparent), url(//upload.wikimedia.org/wikipedia/commons/6/65/Lock-green.svg) right 0.1em center/9px no-repeat; } .id-lock-limited a, .id-lock-registration a, .citation .cs1-lock-limited a, .citation .cs1-lock-registration a { background: linear-gradient(transparent, transparent), url(//upload.wikimedia.org/wikipedia/commons/d/d6/Lock-gray-alt-2.svg) right 0.1em center/9px no-repeat; } .id-lock-subscription a, .citation .cs1-lock-subscription a { background: linear-gradient(transparent, transparent), url(//upload.wikimedia.org/wikipedia/commons/a/aa/Lock-red-alt-2.svg) right 0.1em center/9px no-repeat; } /* Wikisource Wikisource icon when |chapter= or |title= is wikilinked to Wikisource as in cite wikisource */ .cs1-ws-icon a { background: linear-gradient(transparent, transparent), url(//upload.wikimedia.org/wikipedia/commons/4/4c/Wikisource-logo.svg) right 0.1em center/12px no-repeat; } /* Errors and maintenance */ .cs1-code { /* <code>...</code> style override: mediawiki's css definition is specified here: https://git.wikimedia.org/blob/mediawiki%2Fcore.git/ 69cd73811f7aadd093050dbf20ed70ef0b42a713/skins%2Fcommon%2FcommonElements.css#L199 */ color: inherit; background: inherit; border: none; padding: inherit; } .cs1-hidden-error { display: none; color: #d33; } .cs1-visible-error { color: #d33; } .cs1-maint { display: none; color: #3a3; margin-left: 0.3em; } /* Small text size Set small text size in one place. 0.95 (here) * 0.9 (from references list) is ~0.85, which is the lower bound for size for accessibility. Old styling for this was just 0.85. We could write the rule so that when this template is inside references/reflist, only then does it multiply by 0.95; else multiply by 0.85 */ .cs1-format { font-size: 95%; } /* kerning */ .cs1-kern-left { padding-left: 0.2em; } .cs1-kern-right { padding-right: 0.2em; } /* selflinks – avoid bold font style when cs1|2 template links to the current page */ .citation .mw-selflink { font-weight: inherit; } 016143e761e7a41b22296023b6119ee97303dabb Module:Citation/CS1/COinS 828 56 127 2022-01-22T14:11:14Z Canopus >Trappist the monk 0 update per [[Wikipedia:Village_pump_(proposals)#rfc:_shall_we_update_cs1/2?|RfC]]; Scribunto text/plain --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local has_accept_as_written, is_set, in_array, remove_wiki_link, strip_apostrophe_markup; -- functions in Module:Citation/CS1/Utilities local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration --[[--------------------------< M A K E _ C O I N S _ T I T L E >---------------------------------------------- Makes a title for COinS from Title and / or ScriptTitle (or any other name-script pairs) Apostrophe markup (bold, italics) is stripped from each value so that the COinS metadata isn't corrupted with strings of %27%27... ]] local function make_coins_title (title, script) title = has_accept_as_written (title); if is_set (title) then title = strip_apostrophe_markup (title); -- strip any apostrophe markup else title = ''; -- if not set, make sure title is an empty string end if is_set (script) then script = script:gsub ('^%l%l%s*:%s*', ''); -- remove language prefix if present (script value may now be empty string) script = strip_apostrophe_markup (script); -- strip any apostrophe markup else script = ''; -- if not set, make sure script is an empty string end if is_set (title) and is_set (script) then script = ' ' .. script; -- add a space before we concatenate end return title .. script; -- return the concatenation end --[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >---------------------------------- Returns a string where all of Lua's magic characters have been escaped. This is important because functions like string.gsub() treat their pattern and replace strings as patterns, not literal strings. ]] local function escape_lua_magic_chars (argument) argument = argument:gsub("%%", "%%%%"); -- replace % with %% argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other Lua magic pattern characters return argument; end --[[--------------------------< G E T _ C O I N S _ P A G E S >------------------------------------------------ Extract page numbers from external wikilinks in any of the |page=, |pages=, or |at= parameters for use in COinS. ]] local function get_coins_pages (pages) local pattern; if not is_set (pages) then return pages; end -- if no page numbers then we're done while true do pattern = pages:match("%[(%w*:?//[^ ]+%s+)[%w%d].*%]"); -- pattern is the opening bracket, the URL and following space(s): "[url " if nil == pattern then break; end -- no more URLs pattern = escape_lua_magic_chars (pattern); -- pattern is not a literal string; escape Lua's magic pattern characters pages = pages:gsub(pattern, ""); -- remove as many instances of pattern as possible end pages = pages:gsub("[%[%]]", ""); -- remove the brackets pages = pages:gsub("–", "-" ); -- replace endashes with hyphens pages = pages:gsub("&%w+;", "-" ); -- and replace HTML entities (&ndash; etc.) with hyphens; do we need to replace numerical entities like &#32; and the like? return pages; end --[=[-------------------------< C O I N S _ R E P L A C E _ M A T H _ S T R I P M A R K E R >------------------ There are three options for math markup rendering that depend on the editor's math preference settings. These settings are at [[Special:Preferences#mw-prefsection-rendering]] and are PNG images TeX source MathML with SVG or PNG fallback All three are heavy with HTML and CSS which doesn't belong in the metadata. Without this function, the metadata saved in the raw wikitext contained the rendering determined by the settings of the last editor to save the page. This function gets the rendered form of an equation according to the editor's preference before the page is saved. It then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so that the page is saved without extraneous HTML/CSS markup and with a reasonably readable text form of the equation. When a replacement is made, this function returns true and the value with replacement; otherwise false and the initial value. To replace multipe equations it is necessary to call this function from within a loop. ]=] local function coins_replace_math_stripmarker (value) local stripmarker = cfg.stripmarkers['math']; local rendering = value:match (stripmarker); -- is there a math stripmarker if not rendering then -- when value doesn't have a math stripmarker, abandon this test return false, value; end rendering = mw.text.unstripNoWiki (rendering); -- convert stripmarker into rendered value (or nil? ''? when math render error) if rendering:match ('alt="[^"]+"') then -- if PNG math option rendering = rendering:match ('alt="([^"]+)"'); -- extract just the math text elseif rendering:match ('$%s+.+%s+%$') then -- if TeX math option; $ is legit character that is escapes as \$ rendering = rendering:match ('$%s+(.+)%s+%$') -- extract just the math text elseif rendering:match ('<annotation[^>]+>.+</annotation>') then -- if MathML math option rendering = rendering:match ('<annotation[^>]+>(.+)</annotation>') -- extract just the math text else return false, value; -- had math stripmarker but not one of the three defined forms end return true, value:gsub (stripmarker, rendering, 1); end --[[--------------------------< C O I N S _ C L E A N U P >---------------------------------------------------- Cleanup parameter values for the metadata by removing or replacing invisible characters and certain HTML entities. 2015-12-10: there is a bug in mw.text.unstripNoWiki (). It replaces math stripmarkers with the appropriate content when it shouldn't. See https://phabricator.wikimedia.org/T121085 and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29 TODO: move the replacement patterns and replacement values into a table in /Configuration similar to the invisible characters table? ]] local function coins_cleanup (value) local replaced = true; -- default state to get the do loop running while replaced do -- loop until all math stripmarkers replaced replaced, value = coins_replace_math_stripmarker (value); -- replace math stripmarker with text representation of the equation end value = value:gsub (cfg.stripmarkers['math'], "MATH RENDER ERROR"); -- one or more couldn't be replaced; insert vague error message value = mw.text.unstripNoWiki (value); -- replace nowiki stripmarkers with their content value = value:gsub ('<span class="nowrap" style="padding%-left:0%.1em;">&#39;(s?)</span>', "'%1"); -- replace {{'}} or {{'s}} with simple apostrophe or apostrophe-s value = value:gsub ('&nbsp;', ' '); -- replace &nbsp; entity with plain space value = value:gsub ('\226\128\138', ' '); -- replace hair space with plain space if not mw.ustring.find (value, cfg.indic_script) then -- don't remove zero-width joiner characters from indic script value = value:gsub ('&zwj;', ''); -- remove &zwj; entities value = mw.ustring.gsub (value, '[\226\128\141\226\128\139\194\173]', ''); -- remove zero-width joiner, zero-width space, soft hyphen end value = value:gsub ('[\009\010\013 ]+', ' '); -- replace horizontal tab, line feed, carriage return with plain space return value; end --[[--------------------------< C O I N S >-------------------------------------------------------------------- COinS metadata (see <http://ocoins.info/>) allows automated tools to parse the citation information. ]] local function COinS(data, class) if 'table' ~= type(data) or nil == next(data) then return ''; end for k, v in pairs (data) do -- spin through all of the metadata parameter values if 'ID_list' ~= k and 'Authors' ~= k then -- except the ID_list and Author tables (author nowiki stripmarker done when Author table processed) data[k] = coins_cleanup (v); end end local ctx_ver = "Z39.88-2004"; -- treat table strictly as an array with only set values. local OCinSoutput = setmetatable( {}, { __newindex = function(self, key, value) if is_set(value) then rawset( self, #self+1, table.concat{ key, '=', mw.uri.encode( remove_wiki_link( value ) ) } ); end end }); if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn', 'journal', 'news', 'magazine'}) or (in_array (class, {'conference', 'interview', 'map', 'press release', 'web'}) and is_set(data.Periodical)) or ('citation' == class and is_set(data.Periodical) and not is_set (data.Encyclopedia)) then OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"; -- journal metadata identifier if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) then -- set genre according to the type of citation template we are rendering OCinSoutput["rft.genre"] = "preprint"; -- cite arxiv, cite biorxiv, cite citeseerx, cite ssrn elseif 'conference' == class then OCinSoutput["rft.genre"] = "conference"; -- cite conference (when Periodical set) elseif 'web' == class then OCinSoutput["rft.genre"] = "unknown"; -- cite web (when Periodical set) else OCinSoutput["rft.genre"] = "article"; -- journal and other 'periodical' articles end OCinSoutput["rft.jtitle"] = data.Periodical; -- journal only OCinSoutput["rft.atitle"] = data.Title; -- 'periodical' article titles -- these used only for periodicals OCinSoutput["rft.ssn"] = data.Season; -- keywords: winter, spring, summer, fall OCinSoutput["rft.quarter"] = data.Quarter; -- single digits 1->first quarter, etc. OCinSoutput["rft.chron"] = data.Chron; -- free-form date components OCinSoutput["rft.volume"] = data.Volume; -- does not apply to books OCinSoutput["rft.issue"] = data.Issue; OCinSoutput["rft.pages"] = data.Pages; -- also used in book metadata elseif 'thesis' ~= class then -- all others except cite thesis are treated as 'book' metadata; genre distinguishes OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; -- book metadata identifier if 'report' == class or 'techreport' == class then -- cite report and cite techreport OCinSoutput["rft.genre"] = "report"; elseif 'conference' == class then -- cite conference when Periodical not set OCinSoutput["rft.genre"] = "conference"; OCinSoutput["rft.atitle"] = data.Chapter; -- conference paper as chapter in proceedings (book) elseif in_array (class, {'book', 'citation', 'encyclopaedia', 'interview', 'map'}) then if is_set (data.Chapter) then OCinSoutput["rft.genre"] = "bookitem"; OCinSoutput["rft.atitle"] = data.Chapter; -- book chapter, encyclopedia article, interview in a book, or map title else if 'map' == class or 'interview' == class then OCinSoutput["rft.genre"] = 'unknown'; -- standalone map or interview else OCinSoutput["rft.genre"] = 'book'; -- book and encyclopedia end end else -- {'audio-visual', 'AV-media-notes', 'DVD-notes', 'episode', 'interview', 'mailinglist', 'map', 'newsgroup', 'podcast', 'press release', 'serial', 'sign', 'speech', 'web'} OCinSoutput["rft.genre"] = "unknown"; end OCinSoutput["rft.btitle"] = data.Title; -- book only OCinSoutput["rft.place"] = data.PublicationPlace; -- book only OCinSoutput["rft.series"] = data.Series; -- book only OCinSoutput["rft.pages"] = data.Pages; -- book, journal OCinSoutput["rft.edition"] = data.Edition; -- book only OCinSoutput["rft.pub"] = data.PublisherName; -- book and dissertation else -- cite thesis OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:dissertation"; -- dissertation metadata identifier OCinSoutput["rft.title"] = data.Title; -- dissertation (also patent but that is not yet supported) OCinSoutput["rft.degree"] = data.Degree; -- dissertation only OCinSoutput['rft.inst'] = data.PublisherName; -- book and dissertation end -- NB. Not currently supported are "info:ofi/fmt:kev:mtx:patent", "info:ofi/fmt:kev:mtx:dc", "info:ofi/fmt:kev:mtx:sch_svc", "info:ofi/fmt:kev:mtx:ctx" -- and now common parameters (as much as possible) OCinSoutput["rft.date"] = data.Date; -- book, journal, dissertation for k, v in pairs( data.ID_list ) do -- what to do about these? For now assume that they are common to all? if k == 'ISBN' then v = v:gsub( "[^-0-9X]", "" ); end local id = cfg.id_handlers[k].COinS; if string.sub( id or "", 1, 4 ) == 'info' then -- for ids that are in the info:registry OCinSoutput["rft_id"] = table.concat{ id, "/", v }; elseif string.sub (id or "", 1, 3 ) == 'rft' then -- for isbn, issn, eissn, etc. that have defined COinS keywords OCinSoutput[ id ] = v; elseif 'url' == id then -- for urls that are assembled in ~/Identifiers; |asin= and |ol= OCinSoutput["rft_id"] = table.concat ({data.ID_list[k], "#id-name=", cfg.id_handlers[k].label}); elseif id then -- when cfg.id_handlers[k].COinS is not nil so urls created here OCinSoutput["rft_id"] = table.concat{ cfg.id_handlers[k].prefix, v, cfg.id_handlers[k].suffix or '', "#id-name=", cfg.id_handlers[k].label }; -- others; provide a URL and indicate identifier name as #fragment (human-readable, but transparent to browsers) end end local last, first; for k, v in ipairs( data.Authors ) do last, first = coins_cleanup (v.last), coins_cleanup (v.first or ''); -- replace any nowiki stripmarkers, non-printing or invisible characters if k == 1 then -- for the first author name only if is_set(last) and is_set(first) then -- set these COinS values if |first= and |last= specify the first author name OCinSoutput["rft.aulast"] = last; -- book, journal, dissertation OCinSoutput["rft.aufirst"] = first; -- book, journal, dissertation elseif is_set(last) then OCinSoutput["rft.au"] = last; -- book, journal, dissertation -- otherwise use this form for the first name end else -- for all other authors if is_set(last) and is_set(first) then OCinSoutput["rft.au"] = table.concat{ last, ", ", first }; -- book, journal, dissertation elseif is_set(last) then OCinSoutput["rft.au"] = last; -- book, journal, dissertation end -- TODO: At present we do not report "et al.". Add anything special if this condition applies? end end OCinSoutput.rft_id = data.URL; OCinSoutput.rfr_id = table.concat{ "info:sid/", mw.site.server:match( "[^/]*$" ), ":", data.RawPage }; -- TODO: Add optional extra info: -- rfr_dat=#REVISION<version> (referrer private data) -- ctx_id=<data.RawPage>#<ref> (identifier for the context object) -- ctx_tim=<ts> (timestamp in format yyyy-mm-ddThh:mm:ssTZD or yyyy-mm-dd) -- ctx_enc=info:ofi/enc:UTF-8 (character encoding) OCinSoutput = setmetatable( OCinSoutput, nil ); -- sort with version string always first, and combine. -- table.sort( OCinSoutput ); table.insert( OCinSoutput, 1, "ctx_ver=" .. ctx_ver ); -- such as "Z39.88-2004" return table.concat(OCinSoutput, "&"); end --[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >-------------------------------------- Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules. ]] local function set_selected_modules (cfg_table_ptr, utilities_page_ptr) cfg = cfg_table_ptr; has_accept_as_written = utilities_page_ptr.has_accept_as_written; -- import functions from selected Module:Citation/CS1/Utilities module is_set = utilities_page_ptr.is_set; in_array = utilities_page_ptr.in_array; remove_wiki_link = utilities_page_ptr.remove_wiki_link; strip_apostrophe_markup = utilities_page_ptr.strip_apostrophe_markup; end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { make_coins_title = make_coins_title, get_coins_pages = get_coins_pages, COinS = COinS, set_selected_modules = set_selected_modules, } 54a5c6fce3535cf48f207524439635ed96505a13 Module:Citation/CS1/Utilities 828 53 121 2022-01-22T14:11:16Z Canopus >Trappist the monk 0 update per [[Wikipedia:Village_pump_(proposals)#rfc:_shall_we_update_cs1/2?|RfC]]; Scribunto text/plain local z = { error_cats_t = {}; -- for categorizing citations that contain errors error_ids_t = {}; -- list of error identifiers; used to prevent duplication of certain errors; local to this module error_msgs_t = {}; -- sequence table of error messages maint_cats_t = {}; -- for categorizing citations that aren't erroneous per se, but could use a little work prop_cats_t = {}; -- for categorizing citations based on certain properties, language of source for instance prop_keys_t = {}; -- for adding classes to the citation's <cite> tag }; --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration --[[--------------------------< I S _ S E T >------------------------------------------------------------------ Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string. ]] local function is_set (var) return not (var == nil or var == ''); end --[[--------------------------< I N _ A R R A Y >-------------------------------------------------------------- Whether needle is in haystack ]] local function in_array (needle, haystack) if needle == nil then return false; end for n, v in ipairs (haystack) do if v == needle then return n; end end return false; end --[[--------------------------< H A S _ A C C E P T _ A S _ W R I T T E N >------------------------------------ When <str> is wholly wrapped in accept-as-written markup, return <str> without markup and true; return <str> and false else with allow_empty = false, <str> must have at least one character inside the markup with allow_empty = true, <str> the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition "has no applicable value" in citation-context. After further evaluation the two cases might be merged at a later stage, but should be kept separated for now. ]] local function has_accept_as_written (str, allow_empty) if not is_set (str) then return str, false; end local count; if true == allow_empty then str, count = str:gsub ('^%(%((.*)%)%)$', '%1'); -- allows (()) to be an empty set else str, count = str:gsub ('^%(%((.+)%)%)$', '%1'); end return str, 0 ~= count; end --[[--------------------------< S U B S T I T U T E >---------------------------------------------------------- Populates numbered arguments in a message string using an argument table. <args> may be a single string or a sequence table of multiple strings. ]] local function substitute (msg, args) return args and mw.message.newRawMessage (msg, args):plain() or msg; end --[[--------------------------< E R R O R _ C O M M E N T >---------------------------------------------------- Wraps error messages with CSS markup according to the state of hidden. <content> may be a single string or a sequence table of multiple strings. ]] local function error_comment (content, hidden) return substitute (hidden and cfg.presentation['hidden-error'] or cfg.presentation['visible-error'], content); end --[[--------------------------< H Y P H E N _ T O _ D A S H >-------------------------------------------------- Converts a hyphen to a dash under certain conditions. The hyphen must separate like items; unlike items are returned unmodified. These forms are modified: letter - letter (A - B) digit - digit (4-5) digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5) letterdigit - letterdigit (A1-A5) (an optional separator between letter and digit is supported – a.1-a.5 or a-1-a-5) digitletter - digitletter (5a - 5d) (an optional separator between letter and digit is supported – 5.a-5.d or 5-a-5-d) any other forms are returned unmodified. str may be a comma- or semicolon-separated list ]] local function hyphen_to_dash (str) if not is_set (str) then return str; end local accept; -- boolean str = str:gsub ("(%(%(.-%)%))", function(m) return m:gsub(",", ","):gsub(";", ";") end) -- replace commas and semicolons in accept-as-written markup with similar unicode characters so they'll be ignored during the split str = str:gsub ('&[nm]dash;', {['&ndash;'] = '–', ['&mdash;'] = '—'}); -- replace &mdash; and &ndash; entities with their characters; semicolon mucks up the text.split str = str:gsub ('&#45;', '-'); -- replace HTML numeric entity with hyphen character str = str:gsub ('&nbsp;', ' '); -- replace &nbsp; entity with generic keyboard space character local out = {}; local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any for _, item in ipairs (list) do -- for each item in the list item, accept = has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators if item:match ('^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$') or -- letterdigit hyphen letterdigit (optional separator between letter and digit) item:match ('^%d+[%.%-]?%a+%s*%-%s*%d+[%.%-]?%a+$') or -- digitletter hyphen digitletter (optional separator between digit and letter) item:match ('^%d+[%.%-]%d+%s*%-%s*%d+[%.%-]%d+$') or -- digit separator digit hyphen digit separator digit item:match ('^%d+%s*%-%s*%d+$') or -- digit hyphen digit item:match ('^%a+%s*%-%s*%a+$') then -- letter hyphen letter item = item:gsub ('(%w*[%.%-]?%w+)%s*%-%s*(%w*[%.%-]?%w+)', '%1–%2'); -- replace hyphen, remove extraneous space characters else item = mw.ustring.gsub (item, '%s*[–—]%s*', '–'); -- for endash or emdash separated ranges, replace em with en, remove extraneous whitespace end end table.insert (out, item); -- add the (possibly modified) item to the output table end local temp_str = ''; -- concatenate the output table into a comma separated string temp_str, accept = has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out if accept then temp_str = has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value return temp_str:gsub(",", ","):gsub(";", ";"); else return temp_str:gsub(",", ","):gsub(";", ";"); -- else, return assembled temp_str end end --[=[-------------------------< M A K E _ W I K I L I N K >---------------------------------------------------- Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only link is provided (or link and display are the same), returns a wikilink in the form [[L]]; if neither are provided or link is omitted, returns an empty string. ]=] local function make_wikilink (link, display) if not is_set (link) then return '' end if is_set (display) and link ~= display then return table.concat ({'[[', link, '|', display, ']]'}); else return table.concat ({'[[', link, ']]'}); end end --[[--------------------------< S E T _ M E S S A G E >---------------------------------------------------------- Sets an error message using the ~/Configuration error_conditions{} table along with arguments supplied in the function call, inserts the resulting message in z.error_msgs_t{} sequence table, and returns the error message. <error_id> – key value for appropriate error handler in ~/Configuration error_conditions{} table <arguments> – may be a single string or a sequence table of multiple strings to be subsititued into error_conditions[error_id].message <raw> – boolean true – causes this function to return the error message not wrapped in visible-error, hidden-error span tag; returns error_conditions[error_id].hidden as a second return value does not add message to z.error_msgs_t sequence table false, nil – adds message wrapped in visible-error, hidden-error span tag to z.error_msgs_t returns the error message wrapped in visible-error, hidden-error span tag; there is no second return value <prefix> – string to be prepended to <message> -- TODO: remove support for these unused(?) arguments? <suffix> – string to be appended to <message> TODO: change z.error_cats_t and z.maint_cats_t to have the form cat_name = true? this to avoid dups without having to have an extra table ]] local added_maint_cats = {} -- list of maintenance categories that have been added to z.maint_cats_t; TODO: figure out how to delete this table local function set_message (error_id, arguments, raw, prefix, suffix) local error_state = cfg.error_conditions[error_id]; prefix = prefix or ''; suffix = suffix or ''; if error_state == nil then error (cfg.messages['undefined_error'] .. ': ' .. error_id); -- because missing error handler in Module:Citation/CS1/Configuration elseif is_set (error_state.category) then if error_state.message then -- when error_state.message defined, this is an error message table.insert (z.error_cats_t, error_state.category); else if not added_maint_cats[error_id] then added_maint_cats[error_id] = true; -- note that we've added this category table.insert (z.maint_cats_t, substitute (error_state.category, arguments)); -- make cat name then add to table end return; -- because no message, nothing more to do end end local message = substitute (error_state.message, arguments); message = table.concat ( { message, ' (', make_wikilink ( table.concat ( { cfg.messages['help page link'], '#', error_state.anchor }), cfg.messages['help page label']), ')' }); z.error_ids_t[error_id] = true; if z.error_ids_t['err_citation_missing_title'] and -- if missing-title error already noted in_array (error_id, {'err_bare_url_missing_title', 'err_trans_missing_title'}) then -- and this error is one of these return '', false; -- don't bother because one flavor of missing title is sufficient end message = table.concat ({prefix, message, suffix}); if true == raw then return message, error_state.hidden; -- return message not wrapped in visible-error, hidden-error span tag end message = error_comment (message, error_state.hidden); -- wrap message in visible-error, hidden-error span tag table.insert (z.error_msgs_t, message); -- add it to the messages sequence table return message; -- and done; return value generally not used but is used as a flag in various functions of ~/Identifiers end --[[-------------------------< I S _ A L I A S _ U S E D >----------------------------------------------------- This function is used by select_one() to determine if one of a list of alias parameters is in the argument list provided by the template. Input: args – pointer to the arguments table from calling template alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration index – for enumerated parameters, identifies which one enumerated – true/false flag used to choose how enumerated aliases are examined value – value associated with an alias that has previously been selected; nil if not yet selected selected – the alias that has previously been selected; nil if not yet selected error_list – list of aliases that are duplicates of the alias already selected Returns: value – value associated with alias we selected or that was previously selected or nil if an alias not yet selected selected – the alias we selected or the alias that was previously selected or nil if an alias not yet selected ]] local function is_alias_used (args, alias, index, enumerated, value, selected, error_list) if enumerated then -- is this a test for an enumerated parameters? alias = alias:gsub ('#', index); -- replace '#' with the value in index else alias = alias:gsub ('#', ''); -- remove '#' if it exists end if is_set (args[alias]) then -- alias is in the template's argument list if value ~= nil and selected ~= alias then -- if we have already selected one of the aliases local skip; for _, v in ipairs (error_list) do -- spin through the error list to see if we've added this alias if v == alias then skip = true; break; -- has been added so stop looking end end if not skip then -- has not been added so table.insert (error_list, alias); -- add error alias to the error list end else value = args[alias]; -- not yet selected an alias, so select this one selected = alias; end end return value, selected; -- return newly selected alias, or previously selected alias end --[[--------------------------< A D D _ M A I N T _ C A T >------------------------------------------------------ Adds a category to z.maint_cats_t using names from the configuration file with additional text if any. To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maint_cats_t. ]] local function add_maint_cat (key, arguments) if not added_maint_cats [key] then added_maint_cats [key] = true; -- note that we've added this category table.insert (z.maint_cats_t, substitute (cfg.maint_cats [key], arguments)); -- make name then add to table end end --[[--------------------------< A D D _ P R O P _ C A T >-------------------------------------------------------- Adds a category to z.prop_cats_t using names from the configuration file with additional text if any. foreign_lang_source and foreign_lang_source_2 keys have a language code appended to them so that multiple languages may be categorized but multiples of the same language are not categorized. added_prop_cats is a table declared in page scope variables above ]] local added_prop_cats = {}; -- list of property categories that have been added to z.prop_cats_t local function add_prop_cat (key, arguments, key_modifier) local key_modified = key .. ((key_modifier and key_modifier) or ''); -- modify <key> with <key_modifier> if present and not nil if not added_prop_cats [key_modified] then added_prop_cats [key_modified] = true; -- note that we've added this category table.insert (z.prop_cats_t, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table table.insert (z.prop_keys_t, 'cs1-prop-' .. key); -- convert key to class for use in the citation's <cite> tag end end --[[--------------------------< S A F E _ F O R _ I T A L I C S >---------------------------------------------- Protects a string that will be wrapped in wiki italic markup '' ... '' Note: We cannot use <i> for italics, as the expected behavior for italics specified by ''...'' in the title is that they will be inverted (i.e. unitalicized) in the resulting references. In addition, <i> and '' tend to interact poorly under Mediawiki's HTML tidy. ]] local function safe_for_italics (str) if not is_set (str) then return str end if str:sub (1, 1) == "'" then str = "<span></span>" .. str; end if str:sub (-1, -1) == "'" then str = str .. "<span></span>"; end return str:gsub ('\n', ' '); -- Remove newlines as they break italics. end --[[--------------------------< W R A P _ S T Y L E >---------------------------------------------------------- Applies styling to various parameters. Supplied string is wrapped using a message_list configuration taking one argument; protects italic styled parameters. Additional text taken from citation_config.presentation - the reason this function is similar to but separate from wrap_msg(). ]] local function wrap_style (key, str) if not is_set (str) then return ""; elseif in_array (key, {'italic-title', 'trans-italic-title'}) then str = safe_for_italics (str); end return substitute (cfg.presentation[key], {str}); end --[[--------------------------< M A K E _ S E P _ L I S T >------------------------------------------------------------ make a separated list of items using provided separators. <sep_list> - typically '<comma><space>' <sep_list_pair> - typically '<space>and<space>' <sep_list_end> - typically '<comma><space>and<space>' or '<comma><space>&<space>' defaults to cfg.presentation['sep_list'], cfg.presentation['sep_list_pair'], and cfg.presentation['sep_list_end'] if <sep_list_end> is specified, <sep_list> and <sep_list_pair> must also be supplied ]] local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end) local list = ''; if not sep_list then -- set the defaults sep_list = cfg.presentation['sep_list']; sep_list_pair = cfg.presentation['sep_list_pair']; sep_list_end = cfg.presentation['sep_list_end']; end if 2 >= count then list = table.concat (list_seq, sep_list_pair); -- insert separator between two items; returns list_seq[1] then only one item elseif 2 < count then list = table.concat (list_seq, sep_list, 1, count - 1); -- concatenate all but last item with plain list separator list = table.concat ({list, list_seq[count]}, sep_list_end); -- concatenate last item onto end of <list> with final separator end return list; end --[[--------------------------< S E L E C T _ O N E >---------------------------------------------------------- Chooses one matching parameter from a list of parameters to consider. The list of parameters to consider is just names. For parameters that may be enumerated, the position of the numerator in the parameter name is identified by the '#' so |author-last1= and |author1-last= are represented as 'author-last#' and 'author#-last'. Because enumerated parameter |<param>1= is an alias of |<param>= we must test for both possibilities. Generates an error if more than one match is present. ]] local function select_one (args, aliases_list, error_condition, index) local value = nil; -- the value assigned to the selected parameter local selected = ''; -- the name of the parameter we have chosen local error_list = {}; if index ~= nil then index = tostring(index); end for _, alias in ipairs (aliases_list) do -- for each alias in the aliases list if alias:match ('#') then -- if this alias can be enumerated if '1' == index then -- when index is 1 test for enumerated and non-enumerated aliases value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- first test for non-enumerated alias end value, selected = is_alias_used (args, alias, index, true, value, selected, error_list); -- test for enumerated alias else value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- test for non-enumerated alias end end if #error_list > 0 and 'none' ~= error_condition then -- for cases where this code is used outside of extract_names() for i, v in ipairs (error_list) do error_list[i] = wrap_style ('parameter', v); end table.insert (error_list, wrap_style ('parameter', selected)); set_message (error_condition, {make_sep_list (#error_list, error_list)}); end return value, selected; end --[=[-------------------------< R E M O V E _ W I K I _ L I N K >---------------------------------------------- Gets the display text from a wikilink like [[A|B]] or [[B]] gives B The str:gsub() returns either A|B froma [[A|B]] or B from [[B]] or B from B (no wikilink markup). In l(), l:gsub() removes the link and pipe (if they exist); the second :gsub() trims whitespace from the label if str was wrapped in wikilink markup. Presumably, this is because without wikimarkup in str, there is no match in the initial gsub, the replacement function l() doesn't get called. ]=] local function remove_wiki_link (str) return (str:gsub ("%[%[([^%[%]]*)%]%]", function(l) return l:gsub ("^[^|]*|(.*)$", "%1" ):gsub ("^%s*(.-)%s*$", "%1"); end)); end --[=[-------------------------< I S _ W I K I L I N K >-------------------------------------------------------- Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts. If str is a complex wikilink ([[L|D]]): returns wl_type 2 and D and L from [[L|D]]; if str is a simple wikilink ([[D]]) returns wl_type 1 and D from [[D]] and L as empty string; if not a wikilink: returns wl_type 0, str as D, and L as empty string. trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes). ]=] local function is_wikilink (str) local D, L local wl_type = 2; -- assume that str is a complex wikilink [[L|D]] if not str:match ('^%[%[[^%]]+%]%]$') then -- is str some sort of a wikilink (must have some sort of content) return 0, str, ''; -- not a wikilink; return wl_type as 0, str as D, and empty string as L end L, D = str:match ('^%[%[([^|]+)|([^%]]+)%]%]$'); -- get L and D from [[L|D]] if not is_set (D) then -- if no separate display D = str:match ('^%[%[([^%]]*)|*%]%]$'); -- get D from [[D]] or [[D|]] wl_type = 1; end D = mw.text.trim (D, '%s|'); -- trim white space and pipe characters return wl_type, D, L or ''; end --[[--------------------------< S T R I P _ A P O S T R O P H E _ M A R K U P >-------------------------------- Strip wiki italic and bold markup from argument so that it doesn't contaminate COinS metadata. This function strips common patterns of apostrophe markup. We presume that editors who have taken the time to markup a title have, as a result, provided valid markup. When they don't, some single apostrophes are left behind. Returns the argument without wiki markup and a number; the number is more-or-less meaningless except as a flag to indicate that markup was replaced; do not rely on it as an indicator of how many of any kind of markup was removed; returns the argument and nil when no markup removed ]] local function strip_apostrophe_markup (argument) if not is_set (argument) then return argument, nil; -- no argument, nothing to do end if nil == argument:find ( "''", 1, true ) then -- Is there at least one double apostrophe? If not, exit. return argument, nil; end local flag; while true do if argument:find ("'''''", 1, true) then -- bold italic (5) argument, flag = argument:gsub ("%'%'%'%'%'", ""); -- remove all instances of it elseif argument:find ("''''", 1, true) then -- italic start and end without content (4) argument, flag=argument:gsub ("%'%'%'%'", ""); elseif argument:find ("'''", 1, true) then -- bold (3) argument, flag=argument:gsub ("%'%'%'", ""); elseif argument:find ("''", 1, true) then -- italic (2) argument, flag = argument:gsub ("%'%'", ""); else break; end end return argument, flag; -- done end --[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >-------------------------------------- Sets local cfg table to same (live or sandbox) as that used by the other modules. ]] local function set_selected_modules (cfg_table_ptr) cfg = cfg_table_ptr; end --[[--------------------------< E X P O R T S >---------------------------------------------------------------- ]] return { add_maint_cat = add_maint_cat, -- exported functions add_prop_cat = add_prop_cat, error_comment = error_comment, has_accept_as_written = has_accept_as_written, hyphen_to_dash = hyphen_to_dash, in_array = in_array, is_set = is_set, is_wikilink = is_wikilink, make_sep_list = make_sep_list, make_wikilink = make_wikilink, remove_wiki_link = remove_wiki_link, safe_for_italics = safe_for_italics, select_one = select_one, set_message = set_message, set_selected_modules = set_selected_modules, strip_apostrophe_markup = strip_apostrophe_markup, substitute = substitute, wrap_style = wrap_style, z = z, -- exported table } b006801b48981b2987f20fc09cbe0dfda525e044 Module:Citation/CS1/Identifiers 828 55 125 2022-01-22T14:11:18Z Canopus >Trappist the monk 0 update per [[Wikipedia:Village_pump_(proposals)#rfc:_shall_we_update_cs1/2?|RfC]]; Scribunto text/plain --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local has_accept_as_written, is_set, in_array, set_message, select_one, -- functions in Module:Citation/CS1/Utilities substitute, make_wikilink; local z; -- table of tables defined in Module:Citation/CS1/Utilities local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration --[[--------------------------< P A G E S C O P E V A R I A B L E S >-------------------------------------- declare variables here that have page-wide scope that are not brought in from other modules; that are created here and used here ]] local auto_link_urls = {}; -- holds identifier URLs for those identifiers that can auto-link |title= --============================<< H E L P E R F U N C T I O N S >>============================================ --[[--------------------------< W I K I D A T A _ A R T I C L E _ N A M E _ G E T >---------------------------- as an aid to internationalizing identifier-label wikilinks, gets identifier article names from Wikidata. returns :<lang code>:<article title> when <q> has an <article title> for <lang code>; nil else for identifiers that do not have q, returns nil for wikis that do not have mw.wikibase installed, returns nil ]] local function wikidata_article_name_get (q) if not is_set (q) or (q and not mw.wikibase) then -- when no q number or when a q number but mw.wikibase not installed on this wiki return nil; -- abandon end local wd_article; local this_wiki_code = cfg.this_wiki_code; -- Wikipedia subdomain; 'en' for en.wikipedia.org wd_article = mw.wikibase.getSitelink (q, this_wiki_code .. 'wiki'); -- fetch article title from WD; nil when no title available at this wiki if wd_article then wd_article = table.concat ({':', this_wiki_code, ':', wd_article}); -- interwiki-style link without brackets if taken from WD; leading colon required end return wd_article; -- article title from WD; nil else end --[[--------------------------< L I N K _ L A B E L _ M A K E >------------------------------------------------ common function to create identifier link label from handler table or from Wikidata returns the first available of 1. redirect from local wiki's handler table (if enabled) 2. Wikidata (if there is a Wikidata entry for this identifier in the local wiki's language) 3. label specified in the local wiki's handler table ]] local function link_label_make (handler) local wd_article; if not (cfg.use_identifier_redirects and is_set (handler.redirect)) then -- redirect has priority so if enabled and available don't fetch from Wikidata because expensive wd_article = wikidata_article_name_get (handler.q); -- if Wikidata has an article title for this wiki, get it; end return (cfg.use_identifier_redirects and is_set (handler.redirect) and handler.redirect) or wd_article or handler.link; end --[[--------------------------< E X T E R N A L _ L I N K _ I D >---------------------------------------------- Formats a wiki-style external link ]] local function external_link_id (options) local url_string = options.id; local ext_link; local this_wiki_code = cfg.this_wiki_code; -- Wikipedia subdomain; 'en' for en.wikipedia.org local wd_article; -- article title from Wikidata if options.encode == true or options.encode == nil then url_string = mw.uri.encode (url_string, 'PATH'); end if options.auto_link and is_set (options.access) then auto_link_urls[options.auto_link] = table.concat ({options.prefix, url_string, options.suffix}); end ext_link = mw.ustring.format ('[%s%s%s %s]', options.prefix, url_string, options.suffix or "", mw.text.nowiki (options.id)); if is_set (options.access) then ext_link = substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[options.access].class, cfg.presentation[options.access].title, ext_link}); -- add the free-to-read / paywall lock end return table.concat ({ make_wikilink (link_label_make (options), options.label), -- redirect, Wikidata link, or locally specified link (in that order) options.separator or '&nbsp;', ext_link }); end --[[--------------------------< I N T E R N A L _ L I N K _ I D >---------------------------------------------- Formats a wiki-style internal link TODO: Does not currently need to support options.access, options.encode, auto-linking and COinS (as in external_link_id), but may be needed in the future for :m:Interwiki_map custom-prefixes like :arxiv:, :bibcode:, :DOI:, :hdl:, :ISSN:, :JSTOR:, :Openlibrary:, :PMID:, :RFC:. ]] local function internal_link_id (options) local id = mw.ustring.gsub (options.id, '%d', cfg.date_names.local_digits); -- translate 'local' digits to Western 0-9 return table.concat ( { make_wikilink (link_label_make (options), options.label), -- wiki-link the identifier label options.separator or '&nbsp;', -- add the separator make_wikilink ( table.concat ( { options.prefix, id, -- translated to Western digits options.suffix or '' }), substitute (cfg.presentation['bdi'], {'', mw.text.nowiki (options.id)}) -- bdi tags to prevent Latin script identifiers from being reversed at RTL language wikis ); -- nowiki because MediaWiki still has magic links for ISBN and the like; TODO: is it really required? }); end --[[--------------------------< I S _ E M B A R G O E D >------------------------------------------------------ Determines if a PMC identifier's online version is embargoed. Compares the date in |pmc-embargo-date= against today's date. If embargo date is in the future, returns the content of |pmc-embargo-date=; otherwise, returns an empty string because the embargo has expired or because |pmc-embargo-date= was not set in this cite. ]] local function is_embargoed (embargo) if is_set (embargo) then local lang = mw.getContentLanguage(); local good1, embargo_date, todays_date; good1, embargo_date = pcall (lang.formatDate, lang, 'U', embargo); todays_date = lang:formatDate ('U'); if good1 then -- if embargo date is a good date if tonumber (embargo_date) >= tonumber (todays_date) then -- is embargo date is in the future? return embargo; -- still embargoed else set_message ('maint_pmc_embargo'); -- embargo has expired; add main cat return ''; -- unset because embargo has expired end end end return ''; -- |pmc-embargo-date= not set return empty string end --[=[-------------------------< I S _ V A L I D _ B I O R X I V _ D A T E >------------------------------------ returns true if: 2019-12-11T00:00Z <= biorxiv_date < today + 2 days The dated form of biorxiv identifier has a start date of 2019-12-11. The Unix timestamp for that date is {{#time:U|2019-12-11}} = 1576022400 biorxiv_date is the date provided in those |biorxiv= parameter values that are dated at time 00:00:00 UTC today is the current date at time 00:00:00 UTC plus 48 hours if today is 2015-01-01T00:00:00 then adding 24 hours gives 2015-01-02T00:00:00 – one second more than today adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow This function does not work if it is fed month names for languages other than English. Wikimedia #time: parser apparently doesn't understand non-English date month names. This function will always return false when the date contains a non-English month name because good1 is false after the call to lang_object.formatDate(). To get around that call this function with date parts and create a YYYY-MM-DD format date. ]=] local function is_valid_biorxiv_date (y, m, d) local biorxiv_date = table.concat ({y, m, d}, '-'); -- make ymd date local good1, good2; local biorxiv_ts, tomorrow_ts; -- to hold Unix timestamps representing the dates local lang_object = mw.getContentLanguage(); good1, biorxiv_ts = pcall (lang_object.formatDate, lang_object, 'U', biorxiv_date); -- convert biorxiv_date value to Unix timestamp good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow if good1 and good2 then -- lang.formatDate() returns a timestamp in the local script which tonumber() may not understand biorxiv_ts = tonumber (biorxiv_ts) or lang_object:parseFormattedNumber (biorxiv_ts); -- convert to numbers for the comparison; tomorrow_ts = tonumber (tomorrow_ts) or lang_object:parseFormattedNumber (tomorrow_ts); else return false; -- one or both failed to convert to Unix timestamp end return ((1576022400 <= biorxiv_ts) and (biorxiv_ts < tomorrow_ts)) -- 2012-12-11T00:00Z <= biorxiv_date < tomorrow's date end --[[--------------------------< IS _ V A L I D _ I S X N >----------------------------------------------------- ISBN-10 and ISSN validator code calculates checksum across all ISBN/ISSN digits including the check digit. ISBN-13 is checked in isbn(). If the number is valid the result will be 0. Before calling this function, ISBN/ISSN must be checked for length and stripped of dashes, spaces and other non-ISxN characters. ]] local function is_valid_isxn (isxn_str, len) local temp = 0; isxn_str = { isxn_str:byte(1, len) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39, 'X' → 0x58 len = len + 1; -- adjust to be a loop counter for i, v in ipairs (isxn_str) do -- loop through all of the bytes and calculate the checksum if v == string.byte ("X" ) then -- if checkdigit is X (compares the byte value of 'X' which is 0x58) temp = temp + 10 * (len - i); -- it represents 10 decimal else temp = temp + tonumber (string.char (v) )*(len-i); end end return temp % 11 == 0; -- returns true if calculation result is zero end --[[--------------------------< IS _ V A L I D _ I S X N _ 1 3 >----------------------------------------------- ISBN-13 and ISMN validator code calculates checksum across all 13 ISBN/ISMN digits including the check digit. If the number is valid, the result will be 0. Before calling this function, ISBN-13/ISMN must be checked for length and stripped of dashes, spaces and other non-ISxN-13 characters. ]] local function is_valid_isxn_13 (isxn_str) local temp=0; isxn_str = { isxn_str:byte(1, 13) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39 for i, v in ipairs (isxn_str) do temp = temp + (3 - 2*(i % 2)) * tonumber (string.char (v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit end return temp % 10 == 0; -- sum modulo 10 is zero when ISBN-13/ISMN is correct end --[[--------------------------< N O R M A L I Z E _ L C C N >-------------------------------------------------- LCCN normalization (http://www.loc.gov/marc/lccn-namespace.html#normalization) 1. Remove all blanks. 2. If there is a forward slash (/) in the string, remove it, and remove all characters to the right of the forward slash. 3. If there is a hyphen in the string: a. Remove it. b. Inspect the substring following (to the right of) the (removed) hyphen. Then (and assuming that steps 1 and 2 have been carried out): 1. All these characters should be digits, and there should be six or less. (not done in this function) 2. If the length of the substring is less than 6, left-fill the substring with zeroes until the length is six. Returns a normalized LCCN for lccn() to validate. There is no error checking (step 3.b.1) performed in this function. ]] local function normalize_lccn (lccn) lccn = lccn:gsub ("%s", ""); -- 1. strip whitespace if nil ~= string.find (lccn, '/') then lccn = lccn:match ("(.-)/"); -- 2. remove forward slash and all character to the right of it end local prefix local suffix prefix, suffix = lccn:match ("(.+)%-(.+)"); -- 3.a remove hyphen by splitting the string into prefix and suffix if nil ~= suffix then -- if there was a hyphen suffix = string.rep("0", 6-string.len (suffix)) .. suffix; -- 3.b.2 left fill the suffix with 0s if suffix length less than 6 lccn = prefix..suffix; -- reassemble the LCCN end return lccn; end --============================<< I D E N T I F I E R F U N C T I O N S >>==================================== --[[--------------------------< A R X I V >-------------------------------------------------------------------- See: http://arxiv.org/help/arxiv_identifier format and error check arXiv identifier. There are three valid forms of the identifier: the first form, valid only between date codes 9107 and 0703, is: arXiv:<archive>.<class>/<date code><number><version> where: <archive> is a string of alpha characters - may be hyphenated; no other punctuation <class> is a string of alpha characters - may be hyphenated; no other punctuation; not the same as |class= parameter which is not supported in this form <date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01 first digit of YY for this form can only 9 and 0 <number> is a three-digit number <version> is a 1 or more digit number preceded with a lowercase v; no spaces (undocumented) the second form, valid from April 2007 through December 2014 is: arXiv:<date code>.<number><version> where: <date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01 <number> is a four-digit number <version> is a 1 or more digit number preceded with a lowercase v; no spaces the third form, valid from January 2015 is: arXiv:<date code>.<number><version> where: <date code> and <version> are as defined for 0704-1412 <number> is a five-digit number ]] local function arxiv (options) local id = options.id; local class = options.Class; -- TODO: lowercase? local handler = options.handler; local year, month, version; local err_msg = false; -- assume no error message local text; -- output text if id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$") or id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%dv%d+$") then -- test for the 9107-0703 format with or without version year, month = id:match("^%a[%a%.%-]+/([90]%d)([01]%d)%d%d%d[v%d]*$"); year = tonumber (year); month = tonumber (month); if ((not (90 < year or 8 > year)) or (1 > month or 12 < month)) or -- if invalid year or invalid month ((91 == year and 7 > month) or (7 == year and 3 < month)) then -- if years ok, are starting and ending months ok? err_msg = true; -- flag for error message end elseif id:match("^%d%d[01]%d%.%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%dv%d+$") then -- test for the 0704-1412 with or without version year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d[v%d]*$"); year = tonumber (year); month = tonumber (month); if ((7 > year) or (14 < year) or (1 > month or 12 < month)) or -- is year invalid or is month invalid? (doesn't test for future years) ((7 == year) and (4 > month)) then -- when year is 07, is month invalid (before April)? err_msg = true; -- flag for error message end elseif id:match("^%d%d[01]%d%.%d%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%d%dv%d+$") then -- test for the 1501- format with or without version year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d%d[v%d]*$"); year = tonumber (year); month = tonumber (month); if ((15 > year) or (1 > month or 12 < month)) then -- is year invalid or is month invalid? (doesn't test for future years) err_msg = true; -- flag for error message end else err_msg = true; -- not a recognized format; flag for error message end if err_msg then options.coins_list_t['ARXIV'] = nil; -- when error, unset so not included in COinS end local err_msg_t = {}; if err_msg then set_message ('err_bad_arxiv'); end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access}); if is_set (class) then if id:match ('^%d+') then text = table.concat ({text, ' [[//arxiv.org/archive/', class, ' ', class, ']]'}); -- external link within square brackets, not wikilink else set_message ('err_class_ignored'); end end return text; end --[[--------------------------< B I B C O D E >-------------------------------------------------------------------- Validates (sort of) and formats a bibcode ID. Format for bibcodes is specified here: http://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes But, this: 2015arXiv151206696F is apparently valid so apparently, the only things that really matter are length, 19 characters and first four digits must be a year. This function makes these tests: length must be 19 characters characters in position 1–4 must be digits and must represent a year in the range of 1000 – next year 5 must be a letter 6–8 must be letter, digit, ampersand, or dot (ampersand cannot directly precede a dot; &. ) 9–18 must be letter, digit, or dot 19 must be a letter or dot ]] local function bibcode (options) local id = options.id; local access = options.access; local handler = options.handler; local err_type; local err_msg = ''; local year; local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}); if 19 ~= id:len() then err_type = cfg.err_msg_supl.length; else year = id:match ("^(%d%d%d%d)[%a][%w&%.][%w&%.][%w&%.][%w.]+[%a%.]$"); if not year then -- if nil then no pattern match err_type = cfg.err_msg_supl.value; -- so value error else local next_year = tonumber (os.date ('%Y')) + 1; -- get the current year as a number and add one for next year year = tonumber (year); -- convert year portion of bibcode to a number if (1000 > year) or (year > next_year) then err_type = cfg.err_msg_supl.year; -- year out of bounds end if id:find('&%.') then err_type = cfg.err_msg_supl.journal; -- journal abbreviation must not have '&.' (if it does it's missing a letter) end end end if is_set (err_type) then -- if there was an error detected set_message ('err_bad_bibcode', {err_type}); options.coins_list_t['BIBCODE'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< B I O R X I V >----------------------------------------------------------------- Format bioRxiv ID and do simple error checking. Before 2019-12-11, biorXiv IDs were 10.1101/ followed by exactly 6 digits. After 2019-12-11, biorXiv IDs retained the six-digit identifier but prefixed that with a yyyy.mm.dd. date and suffixed with an optional version identifier. The bioRxiv ID is the string of characters: https://doi.org/10.1101/078733 -> 10.1101/078733 or a date followed by a six-digit number followed by an optional version indicator 'v' and one or more digits: https://www.biorxiv.org/content/10.1101/2019.12.11.123456v2 -> 10.1101/2019.12.11.123456v2 see https://www.biorxiv.org/about-biorxiv ]] local function biorxiv (options) local id = options.id; local handler = options.handler; local err_msg = true; -- flag; assume that there will be an error local patterns = { '^10.1101/%d%d%d%d%d%d$', -- simple 6-digit identifier (before 2019-12-11) '^10.1101/(20[1-9]%d)%.([01]%d)%.([0-3]%d)%.%d%d%d%d%d%dv%d+$', -- y.m.d. date + 6-digit identifier + version (after 2019-12-11) '^10.1101/(20[1-9]%d)%.([01]%d)%.([0-3]%d)%.%d%d%d%d%d%d$', -- y.m.d. date + 6-digit identifier (after 2019-12-11) } for _, pattern in ipairs (patterns) do -- spin through the patterns looking for a match if id:match (pattern) then local y, m, d = id:match (pattern); -- found a match, attempt to get year, month and date from the identifier if m then -- m is nil when id is the six-digit form if not is_valid_biorxiv_date (y, m, d) then -- validate the encoded date; TODO: don't ignore leap-year and actual month lengths ({{#time:}} is a poor date validator) break; -- date fail; break out early so we don't unset the error message end end err_msg = nil; -- we found a match so unset the error message break; -- and done end end -- err_cat remains set here when no match if err_msg then options.coins_list_t['BIORXIV'] = nil; -- when error, unset so not included in COinS set_message ('err_bad_biorxiv'); -- and set the error message end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access}); end --[[--------------------------< C I T E S E E R X >------------------------------------------------------------ CiteSeerX use their own notion of "doi" (not to be confused with the identifiers resolved via doi.org). The description of the structure of this identifier can be found at Help_talk:Citation_Style_1/Archive_26#CiteSeerX_id_structure ]] local function citeseerx (options) local id = options.id; local handler = options.handler; local matched; local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access}); matched = id:match ("^10%.1%.1%.[1-9]%d?%d?%d?%.[1-9]%d?%d?%d?$"); if not matched then set_message ('err_bad_citeseerx' ); options.coins_list_t['CITESEERX'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< D O I >------------------------------------------------------------------------ Formats a DOI and checks for DOI errors. DOI names contain two parts: prefix and suffix separated by a forward slash. Prefix: directory indicator '10.' followed by a registrant code Suffix: character string of any length chosen by the registrant This function checks a DOI name for: prefix/suffix. If the DOI name contains spaces or endashes, or, if it ends with a period or a comma, this function will emit a bad_doi error message. DOI names are case-insensitive and can incorporate any printable Unicode characters so the test for spaces, endash, and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely if ever used in DOI names. ]] local function doi (options) local id = options.id; local inactive = options.DoiBroken local access = options.access; local ignore_invalid = options.accept; local handler = options.handler; local err_flag; local text; if is_set (inactive) then local inactive_year = inactive:match("%d%d%d%d") or ''; -- try to get the year portion from the inactive date local inactive_month, good; if is_set (inactive_year) then if 4 < inactive:len() then -- inactive date has more than just a year (could be anything) local lang_obj = mw.getContentLanguage(); -- get a language object for this wiki good, inactive_month = pcall (lang_obj.formatDate, lang_obj, 'F', inactive); -- try to get the month name from the inactive date if not good then inactive_month = nil; -- something went wrong so make sure this is unset end end else inactive_year = nil; -- |doi-broken-date= has something but it isn't a date end if is_set (inactive_year) and is_set (inactive_month) then set_message ('maint_doi_inactive_dated', {inactive_year, inactive_month, ' '}); elseif is_set (inactive_year) then set_message ('maint_doi_inactive_dated', {inactive_year, '', ''}); else set_message ('maint_doi_inactive'); end inactive = " (" .. cfg.messages['inactive'] .. ' ' .. inactive .. ')'; end local registrant = mw.ustring.match (id, '^10%.([^/]+)/[^%s–]-[^%.,]$'); -- registrant set when DOI has the proper basic form local registrant_err_patterns = { -- these patterns are for code ranges that are not supported '^[^1-3]%d%d%d%d%.%d%d*$', -- 5 digits with subcode (0xxxx, 40000+); accepts: 10000–39999 '^[^1-5]%d%d%d%d$', -- 5 digits without subcode (0xxxx, 60000+); accepts: 10000–59999 '^[^1-9]%d%d%d%.%d%d*$', -- 4 digits with subcode (0xxx); accepts: 1000–9999 '^[^1-9]%d%d%d$', -- 4 digits without subcode (0xxx); accepts: 1000–9999 '^%d%d%d%d%d%d+', -- 6 or more digits '^%d%d?%d?$', -- less than 4 digits without subcode (with subcode is legitimate) '^5555$', -- test registrant will never resolve '[^%d%.]', -- any character that isn't a digit or a dot } if not ignore_invalid then if registrant then -- when DOI has proper form for i, pattern in ipairs (registrant_err_patterns) do -- spin through error patterns if registrant:match (pattern) then -- to validate registrant codes err_flag = set_message ('err_bad_doi'); -- when found, mark this DOI as bad break; -- and done end end else err_flag = set_message ('err_bad_doi'); -- invalid directory or malformed end else set_message ('maint_doi_ignore'); end if err_flag then options.coins_list_t['DOI'] = nil; -- when error, unset so not included in COinS end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access, auto_link = not (err_flag or is_set (inactive) or ignore_invalid) and 'doi' or nil -- do not auto-link when |doi-broken-date= has a value or when there is a DOI error or (to play it safe, after all, auto-linking is not essential) when invalid DOIs are ignored }) .. (inactive or ''); return text; end --[[--------------------------< H D L >------------------------------------------------------------------------ Formats an HDL with minor error checking. HDL names contain two parts: prefix and suffix separated by a forward slash. Prefix: character string using any character in the UCS-2 character set except '/' Suffix: character string of any length using any character in the UCS-2 character set chosen by the registrant This function checks a HDL name for: prefix/suffix. If the HDL name contains spaces, endashes, or, if it ends with a period or a comma, this function will emit a bad_hdl error message. HDL names are case-insensitive and can incorporate any printable Unicode characters so the test for endashes and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely if ever used in HDLs. Query string parameters are named here: http://www.handle.net/proxy_servlet.html. query strings are not displayed but since '?' is an allowed character in an HDL, '?' followed by one of the query parameters is the only way we have to detect the query string so that it isn't URL-encoded with the rest of the identifier. ]] local function hdl (options) local id = options.id; local access = options.access; local handler = options.handler; local query_params = { -- list of known query parameters from http://www.handle.net/proxy_servlet.html 'noredirect', 'ignore_aliases', 'auth', 'cert', 'index', 'type', 'urlappend', 'locatt', 'action', } local hdl, suffix, param = id:match ('(.-)(%?(%a+).+)$'); -- look for query string local found; if hdl then -- when there are query strings, this is the handle identifier portion for _, q in ipairs (query_params) do -- spin through the list of query parameters if param:match ('^' .. q) then -- if the query string begins with one of the parameters found = true; -- announce a find break; -- and stop looking end end end if found then id = hdl; -- found so replace id with the handle portion; this will be URL-encoded, suffix will not else suffix = ''; -- make sure suffix is empty string for concatenation else end local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, suffix = suffix, separator = handler.separator, encode = handler.encode, access = access}) if nil == id:match("^[^%s–]-/[^%s–]-[^%.,]$") then -- HDL must contain a forward slash, must not contain spaces, endashes, and must not end with period or comma set_message ('err_bad_hdl' ); options.coins_list_t['HDL'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< I S B N >---------------------------------------------------------------------- Determines whether an ISBN string is valid ]] local function isbn (options) local isbn_str = options.id; local ignore_invalid = options.accept; local handler = options.handler; local function return_result (check, err_type) -- local function to handle the various returns local ISBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect, prefix = handler.prefix, id = isbn_str, separator = handler.separator}); if ignore_invalid then -- if ignoring ISBN errors set_message ('maint_isbn_ignore'); -- add a maint category even when there is no error else -- here when not ignoring if not check then -- and there is an error options.coins_list_t['ISBN'] = nil; -- when error, unset so not included in COinS set_message ('err_bad_isbn', err_type); -- set an error message return ISBN; -- return id text end end return ISBN; -- return id text end if nil ~= isbn_str:match ('[^%s-0-9X]') then return return_result (false, cfg.err_msg_supl.char); -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X end local id = isbn_str:gsub ('[%s-]', ''); -- remove hyphens and whitespace local len = id:len(); if len ~= 10 and len ~= 13 then return return_result (false, cfg.err_msg_supl.length); -- fail if incorrect length end if len == 10 then if id:match ('^%d*X?$') == nil then -- fail if isbn_str has 'X' anywhere but last position return return_result (false, cfg.err_msg_supl.form); end if not is_valid_isxn (id, 10) then -- test isbn-10 for numerical validity return return_result (false, cfg.err_msg_supl.check); -- fail if isbn-10 is not numerically valid end if id:find ('^63[01]') then -- 630xxxxxxx and 631xxxxxxx are (apparently) not valid isbn group ids but are used by amazon as numeric identifiers (asin) return return_result (false, cfg.err_msg_supl.group); -- fail if isbn-10 begins with 630/1 end return return_result (true, cfg.err_msg_supl.check); -- pass if isbn-10 is numerically valid else if id:match ('^%d+$') == nil then return return_result (false, cfg.err_msg_supl.char); -- fail if ISBN-13 is not all digits end if id:match ('^97[89]%d*$') == nil then return return_result (false, cfg.err_msg_supl.prefix); -- fail when ISBN-13 does not begin with 978 or 979 end if id:match ('^9790') then return return_result (false, cfg.err_msg_supl.group); -- group identifier '0' is reserved to ISMN end return return_result (is_valid_isxn_13 (id), cfg.err_msg_supl.check); end end --[[--------------------------< A S I N >---------------------------------------------------------------------- Formats a link to Amazon. Do simple error checking: ASIN must be mix of 10 numeric or uppercase alpha characters. If a mix, first character must be uppercase alpha; if all numeric, ASINs must be 10-digit ISBN. If 10-digit ISBN, add a maintenance category so a bot or AWB script can replace |asin= with |isbn=. Error message if not 10 characters, if not ISBN-10, if mixed and first character is a digit. |asin=630....... and |asin=631....... are (apparently) not a legitimate ISBN though it checksums as one; these do not cause this function to emit the maint_asin message This function is positioned here because it calls isbn() ]] local function asin (options) local id = options.id; local domain = options.ASINTLD; local err_flag; if not id:match("^[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$") then err_flag = set_message ('err_bad_asin'); -- ASIN is not a mix of 10 uppercase alpha and numeric characters else if id:match("^%d%d%d%d%d%d%d%d%d[%dX]$") then -- if 10-digit numeric (or 9 digits with terminal X) if is_valid_isxn (id, 10) then -- see if ASIN value is or validates as ISBN-10 if not id:find ('^63[01]') then -- 630xxxxxxx and 631xxxxxxx are (apparently) not a valid isbn prefixes but are used by amazon as a numeric identifier err_flag = set_message ('err_bad_asin'); -- ASIN has ISBN-10 form but begins with something other than 630/1 so probably an isbn end elseif not is_set (err_flag) then err_flag = set_message ('err_bad_asin'); -- ASIN is not ISBN-10 end elseif not id:match("^%u[%d%u]+$") then err_flag = set_message ('err_bad_asin'); -- asin doesn't begin with uppercase alpha end end if (not is_set (domain)) or in_array (domain, {'us'}) then -- default: United States domain = "com"; elseif in_array (domain, {'jp', 'uk'}) then -- Japan, United Kingdom domain = "co." .. domain; elseif in_array (domain, {'z.cn'}) then -- China domain = "cn"; elseif in_array (domain, {'au', 'br', 'mx', 'sg', 'tr'}) then -- Australia, Brazil, Mexico, Singapore, Turkey domain = "com." .. domain; elseif not in_array (domain, {'ae', 'ca', 'cn', 'de', 'es', 'fr', 'in', 'it', 'nl', 'pl', 'sa', 'se', 'co.jp', 'co.uk', 'com', 'com.au', 'com.br', 'com.mx', 'com.sg', 'com.tr'}) then -- Arabic Emirates, Canada, China, Germany, Spain, France, Indonesia, Italy, Netherlands, Poland, Saudi Arabia, Sweden (as of 2021-03 Austria (.at), Liechtenstein (.li) and Switzerland (.ch) still redirect to the German site (.de) with special settings, so don't maintain local ASINs for them) err_flag = set_message ('err_bad_asin_tld'); -- unsupported asin-tld value end local handler = options.handler; if not is_set (err_flag) then options.coins_list_t['ASIN'] = handler.prefix .. domain .. "/dp/" .. id; -- asin for coins else options.coins_list_t['ASIN'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix .. domain .. "/dp/", id = id, encode = handler.encode, separator = handler.separator}) end --[[--------------------------< I S M N >---------------------------------------------------------------------- Determines whether an ISMN string is valid. Similar to ISBN-13, ISMN is 13 digits beginning 979-0-... and uses the same check digit calculations. See http://www.ismn-international.org/download/Web_ISMN_Users_Manual_2008-6.pdf section 2, pages 9–12. ismn value not made part of COinS metadata because we don't have a url or isn't a COinS-defined identifier (rft.xxx) or an identifier registered at info-uri.info (info:) ]] local function ismn (options) local id = options.id; local handler = options.handler; local text; local valid_ismn = true; local id_copy; id_copy = id; -- save a copy because this testing is destructive id = id:gsub ('[%s-]', ''); -- remove hyphens and white space if 13 ~= id:len() or id:match ("^9790%d*$" ) == nil then -- ISMN must be 13 digits and begin with 9790 valid_ismn = false; else valid_ismn=is_valid_isxn_13 (id); -- validate ISMN end -- text = internal_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, -- use this (or external version) when there is some place to link to -- prefix = handler.prefix, id = id_copy, separator = handler.separator, encode = handler.encode}) text = table.concat ( -- because no place to link to yet { make_wikilink (link_label_make (handler), handler.label), handler.separator, id_copy }); if false == valid_ismn then options.coins_list_t['ISMN'] = nil; -- when error, unset so not included in COinS; not really necessary here because ismn not made part of COinS set_message ('err_bad_ismn'); -- create an error message if the ISMN is invalid end return text; end --[[--------------------------< I S S N >---------------------------------------------------------------------- Validate and format an ISSN. This code fixes the case where an editor has included an ISSN in the citation but has separated the two groups of four digits with a space. When that condition occurred, the resulting link looked like this: |issn=0819 4327 gives: [http://www.worldcat.org/issn/0819 4327 0819 4327] -- can't have spaces in an external link This code now prevents that by inserting a hyphen at the ISSN midpoint. It also validates the ISSN for length and makes sure that the checkdigit agrees with the calculated value. Incorrect length (8 digits), characters other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check ISSN error message. The ISSN is always displayed with a hyphen, even if the ISSN was given as a single group of 8 digits. ]] local function issn (options) local id = options.id; local handler = options.handler; local ignore_invalid = options.accept; local issn_copy = id; -- save a copy of unadulterated ISSN; use this version for display if ISSN does not validate local text; local valid_issn = true; id = id:gsub ('[%s-]', ''); -- remove hyphens and whitespace if 8 ~= id:len() or nil == id:match ("^%d*X?$" ) then -- validate the ISSN: 8 digits long, containing only 0-9 or X in the last position valid_issn = false; -- wrong length or improper character else valid_issn = is_valid_isxn (id, 8); -- validate ISSN end if true == valid_issn then id = string.sub (id, 1, 4 ) .. "-" .. string.sub (id, 5 ); -- if valid, display correctly formatted version else id = issn_copy; -- if not valid, show the invalid ISSN with error message end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}) if ignore_invalid then set_message ('maint_issn_ignore'); else if false == valid_issn then options.coins_list_t['ISSN'] = nil; -- when error, unset so not included in COinS set_message ('err_bad_issn', (options.hkey == 'EISSN') and 'e' or ''); -- create an error message if the ISSN is invalid end end return text; end --[[--------------------------< J F M >----------------------------------------------------------------------- A numerical identifier in the form nn.nnnn.nn ]] local function jfm (options) local id = options.id; local handler = options.handler; local id_num; id_num = id:match ('^[Jj][Ff][Mm](.*)$'); -- identifier with jfm prefix; extract identifier if is_set (id_num) then set_message ('maint_jfm_format'); else -- plain number without JFM prefix id_num = id; -- if here id does not have prefix end if id_num and id_num:match('^%d%d%.%d%d%d%d%.%d%d$') then id = id_num; -- jfm matches pattern else set_message ('err_bad_jfm' ); -- set an error message options.coins_list_t['JFM'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< J S T O R >-------------------------------------------------------------------- Format a JSTOR with some error checking ]] local function jstor (options) local id = options.id; local access = options.access; local handler = options.handler; if id:find ('[Jj][Ss][Tt][Oo][Rr]') or id:find ('^https?://') or id:find ('%s') then set_message ('err_bad_jstor'); -- set an error message options.coins_list_t['JSTOR'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}); end --[[--------------------------< L C C N >---------------------------------------------------------------------- Format LCCN link and do simple error checking. LCCN is a character string 8-12 characters long. The length of the LCCN dictates the character type of the first 1-3 characters; the rightmost eight are always digits. http://info-uri.info/registry/OAIHandler?verb=GetRecord&metadataPrefix=reg&identifier=info:lccn/ length = 8 then all digits length = 9 then lccn[1] is lowercase alpha length = 10 then lccn[1] and lccn[2] are both lowercase alpha or both digits length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lowercase alpha or both digits length = 12 then lccn[1] and lccn[2] are both lowercase alpha ]] local function lccn (options) local lccn = options.id; local handler = options.handler; local err_flag; -- presume that LCCN is valid local id = lccn; -- local copy of the LCCN id = normalize_lccn (id); -- get canonical form (no whitespace, hyphens, forward slashes) local len = id:len(); -- get the length of the LCCN if 8 == len then if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) err_flag = set_message ('err_bad_lccn'); -- set an error message end elseif 9 == len then -- LCCN should be adddddddd if nil == id:match("%l%d%d%d%d%d%d%d%d") then -- does it match our pattern? err_flag = set_message ('err_bad_lccn'); -- set an error message end elseif 10 == len then -- LCCN should be aadddddddd or dddddddddd if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) ... if nil == id:match("^%l%l%d%d%d%d%d%d%d%d") then -- ... see if it matches our pattern err_flag = set_message ('err_bad_lccn'); -- no match, set an error message end end elseif 11 == len then -- LCCN should be aaadddddddd or adddddddddd if not (id:match("^%l%l%l%d%d%d%d%d%d%d%d") or id:match("^%l%d%d%d%d%d%d%d%d%d%d")) then -- see if it matches one of our patterns err_flag = set_message ('err_bad_lccn'); -- no match, set an error message end elseif 12 == len then -- LCCN should be aadddddddddd if not id:match("^%l%l%d%d%d%d%d%d%d%d%d%d") then -- see if it matches our pattern err_flag = set_message ('err_bad_lccn'); -- no match, set an error message end else err_flag = set_message ('err_bad_lccn'); -- wrong length, set an error message end if not is_set (err_flag) and nil ~= lccn:find ('%s') then err_flag = set_message ('err_bad_lccn'); -- lccn contains a space, set an error message end if is_set (err_flag) then options.coins_list_t['LCCN'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = lccn, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< M R >-------------------------------------------------------------------------- A seven digit number; if not seven digits, zero-fill leading digits to make seven digits. ]] local function mr (options) local id = options.id; local handler = options.handler; local id_num; local id_len; id_num = id:match ('^[Mm][Rr](%d+)$'); -- identifier with mr prefix if is_set (id_num) then set_message ('maint_mr_format'); -- add maint cat else -- plain number without mr prefix id_num = id:match ('^%d+$'); -- if here id is all digits end id_len = id_num and id_num:len() or 0; if (7 >= id_len) and (0 ~= id_len) then id = string.rep ('0', 7-id_len) .. id_num; -- zero-fill leading digits else set_message ('err_bad_mr'); -- set an error message options.coins_list_t['MR'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< O C L C >---------------------------------------------------------------------- Validate and format an OCLC ID. https://www.oclc.org/batchload/controlnumber.en.html {{dead link}} archived at: https://web.archive.org/web/20161228233804/https://www.oclc.org/batchload/controlnumber.en.html ]] local function oclc (options) local id = options.id; local handler = options.handler; local number; if id:match('^ocm%d%d%d%d%d%d%d%d$') then -- ocm prefix and 8 digits; 001 field (12 characters) number = id:match('ocm(%d+)'); -- get the number elseif id:match('^ocn%d%d%d%d%d%d%d%d%d$') then -- ocn prefix and 9 digits; 001 field (12 characters) number = id:match('ocn(%d+)'); -- get the number elseif id:match('^on%d%d%d%d%d%d%d%d%d%d+$') then -- on prefix and 10 or more digits; 001 field (12 characters) number = id:match('^on(%d%d%d%d%d%d%d%d%d%d+)$'); -- get the number elseif id:match('^%(OCoLC%)[1-9]%d*$') then -- (OCoLC) prefix and variable number digits; no leading zeros; 035 field number = id:match('%(OCoLC%)([1-9]%d*)'); -- get the number if 9 < number:len() then number = nil; -- constrain to 1 to 9 digits; change this when OCLC issues 10-digit numbers end elseif id:match('^%d+$') then -- no prefix number = id; -- get the number if 10 < number:len() then number = nil; -- constrain to 1 to 10 digits; change this when OCLC issues 11-digit numbers end end if number then -- proper format id = number; -- exclude prefix, if any, from external link else set_message ('err_bad_oclc') -- add an error message if the id is malformed options.coins_list_t['OCLC'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< O P E N L I B R A R Y >-------------------------------------------------------- Formats an OpenLibrary link, and checks for associated errors. ]] local function openlibrary (options) local id = options.id; local access = options.access; local handler = options.handler; local ident, code = id:gsub('^OL', ''):match("^(%d+([AMW]))$"); -- strip optional OL prefix followed immediately by digits followed by 'A', 'M', or 'W'; local err_flag; local prefix = { -- these are appended to the handler.prefix according to code ['A']='authors/OL', ['M']='books/OL', ['W']='works/OL', ['X']='OL' -- not a code; spoof when 'code' in id is invalid }; if not ident then code = 'X'; -- no code or id completely invalid ident = id; -- copy id to ident so that we display the flawed identifier err_flag = set_message ('err_bad_ol'); end if not is_set (err_flag) then options.coins_list_t['OL'] = handler.prefix .. prefix[code] .. ident; -- experiment for ol coins else options.coins_list_t['OL'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix .. prefix[code], id = ident, separator = handler.separator, encode = handler.encode, access = access}); end --[[--------------------------< O S T I >---------------------------------------------------------------------- Format OSTI and do simple error checking. OSTIs are sequential numbers beginning at 1 and counting up. This code checks the OSTI to see that it contains only digits and is less than test_limit specified in the configuration; the value in test_limit will need to be updated periodically as more OSTIs are issued. NB. 1018 is the lowest OSTI number found in the wild (so far) and resolving OK on the OSTI site ]] local function osti (options) local id = options.id; local access = options.access; local handler = options.handler; if id:match("[^%d]") then -- if OSTI has anything but digits set_message ('err_bad_osti'); -- set an error message options.coins_list_t['OSTI'] = nil; -- when error, unset so not included in COinS else -- OSTI is only digits local id_num = tonumber (id); -- convert id to a number for range testing if 1018 > id_num or handler.id_limit < id_num then -- if OSTI is outside test limit boundaries set_message ('err_bad_osti'); -- set an error message options.coins_list_t['OSTI'] = nil; -- when error, unset so not included in COinS end end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}); end --[[--------------------------< P M C >------------------------------------------------------------------------ Format a PMC, do simple error checking, and check for embargoed articles. The embargo parameter takes a date for a value. If the embargo date is in the future the PMC identifier will not be linked to the article. If the embargo date is today or in the past, or if it is empty or omitted, then the PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].prefix. PMC embargo date testing is done in function is_embargoed () which is called earlier because when the citation has |pmc=<value> but does not have a |url= then |title= is linked with the PMC link. Function is_embargoed () returns the embargo date if the PMC article is still embargoed, otherwise it returns an empty string. PMCs are sequential numbers beginning at 1 and counting up. This code checks the PMC to see that it contains only digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically as more PMCs are issued. ]] local function pmc (options) local id = options.id; local embargo = options.Embargo; -- TODO: lowercase? local handler = options.handler; local err_flag; local id_num; local text; id_num = id:match ('^[Pp][Mm][Cc](%d+)$'); -- identifier with PMC prefix if is_set (id_num) then set_message ('maint_pmc_format'); else -- plain number without PMC prefix id_num = id:match ('^%d+$'); -- if here id is all digits end if is_set (id_num) then -- id_num has a value so test it id_num = tonumber (id_num); -- convert id_num to a number for range testing if 1 > id_num or handler.id_limit < id_num then -- if PMC is outside test limit boundaries err_flag = set_message ('err_bad_pmc'); -- set an error message else id = tostring (id_num); -- make sure id is a string end else -- when id format incorrect err_flag = set_message ('err_bad_pmc'); -- set an error message end if is_set (embargo) and is_set (is_embargoed (embargo)) then -- is PMC is still embargoed? text = table.concat ( -- still embargoed so no external link { make_wikilink (link_label_make (handler), handler.label), handler.separator, id, }); else text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, -- no embargo date or embargo has expired, ok to link to article prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access, auto_link = not err_flag and 'pmc' or nil -- do not auto-link when PMC has error }); end if err_flag then options.coins_list_t['PMC'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< P M I D >---------------------------------------------------------------------- Format PMID and do simple error checking. PMIDs are sequential numbers beginning at 1 and counting up. This code checks the PMID to see that it contains only digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically as more PMIDs are issued. ]] local function pmid (options) local id = options.id; local handler = options.handler; if id:match("[^%d]") then -- if PMID has anything but digits set_message ('err_bad_pmid'); -- set an error message options.coins_list_t['PMID'] = nil; -- when error, unset so not included in COinS else -- PMID is only digits local id_num = tonumber (id); -- convert id to a number for range testing if 1 > id_num or handler.id_limit < id_num then -- if PMID is outside test limit boundaries set_message ('err_bad_pmid'); -- set an error message options.coins_list_t['PMID'] = nil; -- when error, unset so not included in COinS end end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< R F C >------------------------------------------------------------------------ Format RFC and do simple error checking. RFCs are sequential numbers beginning at 1 and counting up. This code checks the RFC to see that it contains only digits and is less than test_limit specified in the configuration; the value in test_limit will need to be updated periodically as more RFCs are issued. An index of all RFCs is here: https://tools.ietf.org/rfc/ ]] local function rfc (options) local id = options.id; local handler = options.handler; if id:match("[^%d]") then -- if RFC has anything but digits set_message ('err_bad_rfc'); -- set an error message options.coins_list_t['RFC'] = nil; -- when error, unset so not included in COinS else -- RFC is only digits local id_num = tonumber (id); -- convert id to a number for range testing if 1 > id_num or handler.id_limit < id_num then -- if RFC is outside test limit boundaries set_message ('err_bad_rfc'); -- set an error message options.coins_list_t['RFC'] = nil; -- when error, unset so not included in COinS end end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access}); end --[[--------------------------< S 2 C I D >-------------------------------------------------------------------- Format an S2CID, do simple error checking S2CIDs are sequential numbers beginning at 1 and counting up. This code checks the S2CID to see that it is only digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically as more S2CIDs are issued. ]] local function s2cid (options) local id = options.id; local access = options.access; local handler = options.handler; local id_num; local text; id_num = id:match ('^[1-9]%d*$'); -- id must be all digits; must not begin with 0; no open access flag if is_set (id_num) then -- id_num has a value so test it id_num = tonumber (id_num); -- convert id_num to a number for range testing if handler.id_limit < id_num then -- if S2CID is outside test limit boundaries set_message ('err_bad_s2cid'); -- set an error message options.coins_list_t['S2CID'] = nil; -- when error, unset so not included in COinS end else -- when id format incorrect set_message ('err_bad_s2cid'); -- set an error message options.coins_list_t['S2CID'] = nil; -- when error, unset so not included in COinS end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}); return text; end --[[--------------------------< S B N >------------------------------------------------------------------------ 9-digit form of ISBN-10; uses same check-digit validation when SBN is prefixed with an additional '0' to make 10 digits sbn value not made part of COinS metadata because we don't have a url or isn't a COinS-defined identifier (rft.xxx) or an identifier registered at info-uri.info (info:) ]] local function sbn (options) local id = options.id; local ignore_invalid = options.accept; local handler = options.handler; local function return_result (check, err_type) -- local function to handle the various returns local SBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator}); if not ignore_invalid then -- if not ignoring SBN errors if not check then options.coins_list_t['SBN'] = nil; -- when error, unset so not included in COinS; not really necessary here because sbn not made part of COinS set_message ('err_bad_sbn', {err_type}); -- display an error message return SBN; end else set_message ('maint_isbn_ignore'); -- add a maint category even when there is no error (ToDo: Possibly switch to separate message for SBNs only) end return SBN; end if id:match ('[^%s-0-9X]') then return return_result (false, cfg.err_msg_supl.char); -- fail if SBN contains anything but digits, hyphens, or the uppercase X end local ident = id:gsub ('[%s-]', ''); -- remove hyphens and whitespace; they interfere with the rest of the tests if 9 ~= ident:len() then return return_result (false, cfg.err_msg_supl.length); -- fail if incorrect length end if ident:match ('^%d*X?$') == nil then return return_result (false, cfg.err_msg_supl.form); -- fail if SBN has 'X' anywhere but last position end return return_result (is_valid_isxn ('0' .. ident, 10), cfg.err_msg_supl.check); end --[[--------------------------< S S R N >---------------------------------------------------------------------- Format an SSRN, do simple error checking SSRNs are sequential numbers beginning at 100? and counting up. This code checks the SSRN to see that it is only digits and is greater than 99 and less than test_limit; the value in local variable test_limit will need to be updated periodically as more SSRNs are issued. ]] local function ssrn (options) local id = options.id; local handler = options.handler; local id_num; local text; id_num = id:match ('^%d+$'); -- id must be all digits if is_set (id_num) then -- id_num has a value so test it id_num = tonumber (id_num); -- convert id_num to a number for range testing if 100 > id_num or handler.id_limit < id_num then -- if SSRN is outside test limit boundaries set_message ('err_bad_ssrn'); -- set an error message options.coins_list_t['SSRN'] = nil; -- when error, unset so not included in COinS end else -- when id format incorrect set_message ('err_bad_ssrn'); -- set an error message options.coins_list_t['SSRN'] = nil; -- when error, unset so not included in COinS end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = options.access}); return text; end --[[--------------------------< U S E N E T _ I D >------------------------------------------------------------ Validate and format a usenet message id. Simple error checking, looks for 'id-left@id-right' not enclosed in '<' and/or '>' angle brackets. ]] local function usenet_id (options) local id = options.id; local handler = options.handler; local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}) if not id:match('^.+@.+$') or not id:match('^[^<].*[^>]$') then -- doesn't have '@' or has one or first or last character is '< or '>' set_message ('err_bad_usenet_id') -- add an error message if the message id is invalid options.coins_list_t['USENETID'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< Z B L >----------------------------------------------------------------------- A numerical identifier in the form nnnn.nnnnn - leading zeros in the first quartet optional format described here: http://emis.mi.sanu.ac.rs/ZMATH/zmath/en/help/search/ temporary format is apparently eight digits. Anything else is an error ]] local function zbl (options) local id = options.id; local handler = options.handler; if id:match('^%d%d%d%d%d%d%d%d$') then -- is this identifier using temporary format? set_message ('maint_zbl'); -- yes, add maint cat elseif not id:match('^%d?%d?%d?%d%.%d%d%d%d%d$') then -- not temporary, is it normal format? set_message ('err_bad_zbl'); -- no, set an error message options.coins_list_t['ZBL'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --============================<< I N T E R F A C E F U N C T I O N S >>========================================== --[[--------------------------< E X T R A C T _ I D S >------------------------------------------------------------ Populates ID table from arguments using configuration settings. Loops through cfg.id_handlers and searches args for any of the parameters listed in each cfg.id_handlers['...'].parameters. If found, adds the parameter and value to the identifier list. Emits redundant error message if more than one alias exists in args ]] local function extract_ids (args) local id_list = {}; -- list of identifiers found in args for k, v in pairs (cfg.id_handlers) do -- k is uppercase identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table v = select_one (args, v.parameters, 'err_redundant_parameters' ); -- v.parameters is a table of aliases for k; here we pick one from args if present if is_set (v) then id_list[k] = v; end -- if found in args, add identifier to our list end return id_list; end --[[--------------------------< E X T R A C T _ I D _ A C C E S S _ L E V E L S >-------------------------------------- Fetches custom id access levels from arguments using configuration settings. Parameters which have a predefined access level (e.g. arxiv) do not use this function as they are directly rendered as free without using an additional parameter. returns a table of k/v pairs where k is same as the identifier's key in cfg.id_handlers and v is the assigned (valid) keyword access-level values must match the case used in cfg.keywords_lists['id-access'] (lowercase unless there is some special reason for something else) ]] local function extract_id_access_levels (args, id_list) local id_accesses_list = {}; for k, v in pairs (cfg.id_handlers) do local access_param = v.custom_access; -- name of identifier's access-level parameter if is_set (access_param) then local access_level = args[access_param]; -- get the assigned value if there is one if is_set (access_level) then if not in_array (access_level, cfg.keywords_lists['id-access']) then -- exact match required set_message ('err_invalid_param_val', {access_param, access_level}); access_level = nil; -- invalid so unset end if not is_set (id_list[k]) then -- identifier access-level must have a matching identifier set_message ('err_param_access_requires_param', {k:lower()}); -- parameter name is uppercase in cfg.id_handlers (k); lowercase for error message end id_accesses_list[k] = cfg.keywords_xlate[access_level]; -- get translated keyword end end end return id_accesses_list; end --[[--------------------------< B U I L D _ I D _ L I S T >---------------------------------------------------- render the identifiers into a sorted sequence table <ID_list_coins_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value <options_t> is a table of various k/v option pairs provided in the call to new_build_id_list(); modified by this function and passed to all identifier rendering functions <access_levels_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value (if valid) returns a sequence table of sorted (by hkey - 'handler' key) rendered identifier strings ]] local function build_id_list (ID_list_coins_t, options_t, access_levels_t) local ID_list_t = {}; local accept; local func_map = { --function map points to functions associated with hkey identifier ['ARXIV'] = arxiv, ['ASIN'] = asin, ['BIBCODE'] = bibcode, ['BIORXIV'] = biorxiv, ['CITESEERX'] = citeseerx, ['DOI'] = doi, ['EISSN'] = issn, ['HDL'] = hdl, ['ISBN'] = isbn, ['ISMN'] = ismn, ['ISSN'] = issn, ['JFM'] = jfm, ['JSTOR'] = jstor, ['LCCN'] = lccn, ['MR'] = mr, ['OCLC'] = oclc, ['OL'] = openlibrary, ['OSTI'] = osti, ['PMC'] = pmc, ['PMID'] = pmid, ['RFC'] = rfc, ['S2CID'] = s2cid, ['SBN'] = sbn, ['SSRN'] = ssrn, ['USENETID'] = usenet_id, ['ZBL'] = zbl, } for hkey, v in pairs (ID_list_coins_t) do v, accept = has_accept_as_written (v); -- remove accept-as-written markup if present; accept is boolean true when markup removed; false else -- every function gets the options table with value v and accept boolean options_t.hkey = hkey; -- ~/Configuration handler key options_t.id = v; -- add that identifier value to the options table options_t.accept = accept; -- add the accept boolean flag options_t.access = access_levels_t[hkey]; -- add the access level for those that have an |<identifier-access= parameter options_t.handler = cfg.id_handlers[hkey]; options_t.coins_list_t = ID_list_coins_t; -- pointer to ID_list_coins_t; for |asin= and |ol=; also to keep erroneous values out of the citation's metadata options_t.coins_list_t[hkey] = v; -- id value without accept-as-written markup for metadata if options_t.handler.access and not in_array (options_t.handler.access, cfg.keywords_lists['id-access']) then error (cfg.messages['unknown_ID_access'] .. options_t.handler.access); -- here when handler access key set to a value not listed in list of allowed id access keywords end if func_map[hkey] then local id_text = func_map[hkey] (options_t); -- call the function to get identifier text and any error message table.insert (ID_list_t, {hkey, id_text}); -- add identifier text to the output sequence table else error (cfg.messages['unknown_ID_key'] .. hkey); -- here when func_map doesn't have a function for hkey end end local function comp (a, b) -- used by following table.sort() return a[1]:lower() < b[1]:lower(); -- sort by hkey end table.sort (ID_list_t, comp); -- sequence table of tables sort for k, v in ipairs (ID_list_t) do -- convert sequence table of tables to simple sequence table of strings ID_list_t[k] = v[2]; -- v[2] is the identifier rendering from the call to the various functions in func_map{} end return ID_list_t; end --[[--------------------------< O P T I O N S _ C H E C K >---------------------------------------------------- check that certain option parameters have their associated identifier parameters with values <ID_list_coins_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value <ID_support_t> is a sequence table of tables created in citation0() where each subtable has four elements: [1] is the support parameter's assigned value; empty string if not set [2] is a text string same as key in cfg.id_handlers [3] is cfg.error_conditions key used to create error message [4] is original ID support parameter name used to create error message returns nothing; on error emits an appropriate error message ]] local function options_check (ID_list_coins_t, ID_support_t) for _, v in ipairs (ID_support_t) do if is_set (v[1]) and not ID_list_coins_t[v[2]] then -- when support parameter has a value but matching identifier parameter is missing or empty set_message (v[3], (v[4])); -- emit the appropriate error message end end end --[[--------------------------< I D E N T I F I E R _ L I S T S _ G E T >-------------------------------------- Creates two identifier lists: a k/v table of identifiers and their values to be used locally and for use in the COinS metadata, and a sequence table of the rendered identifier strings that will be included in the rendered citation. ]] local function identifier_lists_get (args_t, options_t, ID_support_t) local ID_list_coins_t = extract_ids (args_t); -- get a table of identifiers and their values for use locally and for use in COinS options_check (ID_list_coins_t, ID_support_t); -- ID support parameters must have matching identifier parameters local ID_access_levels_t = extract_id_access_levels (args_t, ID_list_coins_t); -- get a table of identifier access levels local ID_list_t = build_id_list (ID_list_coins_t, options_t, ID_access_levels_t); -- get a sequence table of rendered identifier strings return ID_list_t, ID_list_coins_t; -- return the tables end --[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >-------------------------------------- Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules. ]] local function set_selected_modules (cfg_table_ptr, utilities_page_ptr) cfg = cfg_table_ptr; has_accept_as_written = utilities_page_ptr.has_accept_as_written; -- import functions from select Module:Citation/CS1/Utilities module is_set = utilities_page_ptr.is_set; in_array = utilities_page_ptr.in_array; set_message = utilities_page_ptr.set_message; select_one = utilities_page_ptr.select_one; substitute = utilities_page_ptr.substitute; make_wikilink = utilities_page_ptr.make_wikilink; z = utilities_page_ptr.z; -- table of tables in Module:Citation/CS1/Utilities end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { auto_link_urls = auto_link_urls, -- table of identifier URLs to be used when auto-linking |title= identifier_lists_get = identifier_lists_get, -- experiment to replace individual calls to build_id_list(), extract_ids, extract_id_access_levels is_embargoed = is_embargoed; set_selected_modules = set_selected_modules; } 0f40bcba575710f5da9e7d29a8305288fbb30ac4 Module:Citation/CS1/Whitelist 828 52 119 2022-01-22T14:11:22Z Canopus >Trappist the monk 0 update per [[Wikipedia:Village_pump_(proposals)#rfc:_shall_we_update_cs1/2?|RfC]]; Scribunto text/plain --[[--------------------------< S U P P O R T E D P A R A M E T E R S >-------------------------------------- Because a steady-state signal conveys no useful information, whitelist.basic_arguments[] list items can have three values: true - these parameters are valid and supported parameters false - these parameters are deprecated but still supported tracked - these parameters are valid and supported parameters tracked in an eponymous properties category nil - these parameters are no longer supported. remove entirely ]] local basic_arguments = { ['accessdate'] = true, ['access-date'] = true, ['agency'] = true, ['archivedate'] = true, ['archive-date'] = true, ['archive-format'] = true, ['archiveurl'] = true, ['archive-url'] = true, ['article'] = true, ['article-format'] = true, ['article-url'] = true, ['article-url-access'] = true, ['arxiv'] = true, -- cite arxiv; here because allowed in cite ... as identifier ['asin'] = true, ['ASIN'] = true, ['asin-tld'] = true, ['at'] = true, ['author'] = true, ['author-first'] = true, ['author-given'] = true, ['author-last'] = true, ['author-surname'] = true, ['authorlink'] = true, ['author-link'] = true, ['author-mask'] = true, ['authors'] = true, ['bibcode'] = true, ['bibcode-access'] = true, ['biorxiv'] = true, -- cite biorxiv; here because allowed in cite ... as identifier ['chapter'] = true, ['chapter-format'] = true, ['chapter-url'] = true, ['chapter-url-access'] = true, ['citeseerx'] = true, -- cite citeseerx; here because allowed in cite ... as identifier ['collaboration'] = true, ['contribution'] = true, ['contribution-format'] = true, ['contribution-url'] = true, ['contribution-url-access'] = true, ['contributor'] = true, ['contributor-first'] = true, ['contributor-given'] = true, ['contributor-last'] = true, ['contributor-surname'] = true, ['contributor-link'] = true, ['contributor-mask'] = true, ['date'] = true, ['department'] = true, ['df'] = true, ['dictionary'] = true, ['display-authors'] = true, ['display-contributors'] = true, ['display-editors'] = true, ['display-interviewers'] = true, ['display-subjects'] = true, ['display-translators'] = true, ['doi'] = true, ['DOI'] = true, ['doi-access'] = true, ['doi-broken-date'] = true, ['edition'] = true, ['editor'] = true, ['editor-first'] = true, ['editor-given'] = true, ['editor-last'] = true, ['editor-surname'] = true, ['editor-link'] = true, ['editor-mask'] = true, ['eissn'] = true, ['EISSN'] = true, ['encyclopaedia'] = true, ['encyclopedia'] = true, ['entry'] = true, ['entry-format'] = true, ['entry-url'] = true, ['entry-url-access'] = true, ['eprint'] = true, -- cite arxiv; here because allowed in cite ... as identifier ['first'] = true, ['format'] = true, ['given'] = true, ['hdl'] = true, ['HDL'] = true, ['hdl-access'] = true, ['host'] = true, -- unique to certain templates? ['id'] = true, ['ID'] = true, ['institution'] = true, -- constrain to cite thesis? ['interviewer'] = true, ['interviewer-first'] = true, ['interviewer-given'] = true, ['interviewer-last'] = true, ['interviewer-surname'] = true, ['interviewer-link'] = true, ['interviewer-mask'] = true, ['isbn'] = true, ['ISBN'] = true, ['ismn'] = true, ['ISMN'] = true, ['issn'] = true, ['ISSN'] = true, ['issue'] = true, ['jfm'] = true, ['JFM'] = true, ['journal'] = true, ['jstor'] = true, ['JSTOR'] = true, ['jstor-access'] = true, ['lang'] = true, ['language'] = true, ['last'] = true, ['lay-date'] = false, ['lay-format'] = false, ['lay-source'] = false, ['lay-url'] = false, ['lccn'] = true, ['LCCN'] = true, ['location'] = true, ['magazine'] = true, ['medium'] = true, ['minutes'] = true, -- constrain to cite AV media and podcast? ['mode'] = true, ['mr'] = true, ['MR'] = true, ['name-list-style'] = true, ['newspaper'] = true, ['no-pp'] = true, ['no-tracking'] = true, ['number'] = true, ['oclc'] = true, ['OCLC'] = true, ['ol'] = true, ['OL'] = true, ['ol-access'] = true, ['orig-date'] = true, ['origyear'] = true, ['orig-year'] = true, ['osti'] = true, ['OSTI'] = true, ['osti-access'] = true, ['others'] = true, ['p'] = true, ['page'] = true, ['pages'] = true, ['people'] = true, ['periodical'] = true, ['place'] = true, ['pmc'] = true, ['PMC'] = true, ['pmc-embargo-date'] = true, ['pmid'] = true, ['PMID'] = true, ['postscript'] = true, ['pp'] = true, ['publication-date'] = true, ['publication-place'] = true, ['publisher'] = true, ['quotation'] = true, ['quote'] = true, ['quote-page'] = true, ['quote-pages'] = true, ['ref'] = true, ['rfc'] = true, ['RFC'] = true, ['sbn'] = true, ['SBN'] = true, ['scale'] = true, ['script-article'] = true, ['script-chapter'] = true, ['script-contribution'] = true, ['script-entry'] = true, ['script-journal'] = true, ['script-magazine'] = true, ['script-newspaper'] = true, ['script-periodical'] = true, ['script-quote'] = true, ['script-section'] = true, ['script-title'] = true, ['script-website'] = true, ['script-work'] = true, ['section'] = true, ['section-format'] = true, ['section-url'] = true, ['section-url-access'] = true, ['series'] = true, ['ssrn'] = true, -- cite ssrn; these three here because allowed in cite ... as identifier ['SSRN'] = true, ['ssrn-access'] = true, ['subject'] = true, ['subject-link'] = true, ['subject-mask'] = true, ['surname'] = true, ['s2cid'] = true, ['S2CID'] = true, ['s2cid-access'] = true, ['template-doc-demo'] = true, ['time'] = true, -- constrain to cite av media and podcast? ['time-caption'] = true, -- constrain to cite av media and podcast? ['title'] = true, ['title-link'] = true, ['translator'] = true, ['translator-first'] = true, ['translator-given'] = true, ['translator-last'] = true, ['translator-surname'] = true, ['translator-link'] = true, ['translator-mask'] = true, ['trans-article'] = true, ['trans-chapter'] = true, ['trans-contribution'] = true, ['trans-entry'] = true, ['trans-journal'] = true, ['trans-magazine'] = true, ['trans-newspaper'] = true, ['trans-periodical'] = true, ['trans-quote'] = true, ['trans-section'] = true, ['trans-title'] = true, ['trans-website'] = true, ['trans-work'] = true, ['type'] = true, ['url'] = true, ['URL'] = true, ['url-access'] = true, ['url-status'] = true, ['vauthors'] = true, ['veditors'] = true, ['version'] = true, ['via'] = true, ['volume'] = true, ['website'] = true, ['work'] = true, ['year'] = true, ['zbl'] = true, ['ZBL'] = true, } local numbered_arguments = { ['author#'] = true, ['author-first#'] = true, ['author#-first'] = true, ['author-given#'] = true, ['author#-given'] = true, ['author-last#'] = true, ['author#-last'] = true, ['author-surname#'] = true, ['author#-surname'] = true, ['author-link#'] = true, ['author#-link'] = true, ['authorlink#'] = true, ['author#link'] = true, ['author-mask#'] = true, ['author#-mask'] = true, ['contributor#'] = true, ['contributor-first#'] = true, ['contributor#-first'] = true, ['contributor-given#'] = true, ['contributor#-given'] = true, ['contributor-last#'] = true, ['contributor#-last'] = true, ['contributor-surname#'] = true, ['contributor#-surname'] = true, ['contributor-link#'] = true, ['contributor#-link'] = true, ['contributor-mask#'] = true, ['contributor#-mask'] = true, ['editor#'] = true, ['editor-first#'] = true, ['editor#-first'] = true, ['editor-given#'] = true, ['editor#-given'] = true, ['editor-last#'] = true, ['editor#-last'] = true, ['editor-surname#'] = true, ['editor#-surname'] = true, ['editor-link#'] = true, ['editor#-link'] = true, ['editor-mask#'] = true, ['editor#-mask'] = true, ['first#'] = true, ['given#'] = true, ['host#'] = true, ['interviewer#'] = true, ['interviewer-first#'] = true, ['interviewer#-first'] = true, ['interviewer-given#'] = true, ['interviewer#-given'] = true, ['interviewer-last#'] = true, ['interviewer#-last'] = true, ['interviewer-surname#'] = true, ['interviewer#-surname'] = true, ['interviewer-link#'] = true, ['interviewer#-link'] = true, ['interviewer-mask#'] = true, ['interviewer#-mask'] = true, ['last#'] = true, ['subject#'] = true, ['subject-link#'] = true, ['subject#-link'] = true, ['subject-mask#'] = true, ['subject#-mask'] = true, ['surname#'] = true, ['translator#'] = true, ['translator-first#'] = true, ['translator#-first'] = true, ['translator-given#'] = true, ['translator#-given'] = true, ['translator-last#'] = true, ['translator#-last'] = true, ['translator-surname#'] = true, ['translator#-surname'] = true, ['translator-link#'] = true, ['translator#-link'] = true, ['translator-mask#'] = true, ['translator#-mask'] = true, } --[[--------------------------< P R E P R I N T S U P P O R T E D P A R A M E T E R S >-------------------- Cite arXiv, cite biorxiv, cite citeseerx, and cite ssrn are preprint templates that use the limited set of parameters defined in the limited_basic_arguments and limited_numbered_arguments tables. Those lists are supplemented with a template-specific list of parameters that are required by the particular template and may be exclusive to one of the preprint templates. Some of these parameters may also be available to the general cs1|2 templates. Same conventions for true/false/tracked/nil as above. ]] local preprint_arguments = { arxiv = { ['arxiv'] = true, -- cite arxiv and arxiv identifiers ['class'] = true, ['eprint'] = true, -- cite arxiv and arxiv identifiers }, biorxiv = { ['biorxiv'] = true, }, citeseerx = { ['citeseerx'] = true, }, ssrn = { ['ssrn'] = true, ['SSRN'] = true, ['ssrn-access'] = true, }, } --[[--------------------------< L I M I T E D S U P P O R T E D P A R A M E T E R S >---------------------- cite arxiv, cite biorxiv, cite citeseerx, and cite ssrn templates are preprint templates so are allowed only a limited subset of parameters allowed to all other cs1|2 templates. The limited subset is defined here. Same conventions for true/false/tracked/nil as above. ]] local limited_basic_arguments = { ['at'] = true, ['author'] = true, ['author-first'] = true, ['author-given'] = true, ['author-last'] = true, ['author-surname'] = true, ['author-link'] = true, ['authorlink'] = true, ['author-mask'] = true, ['authors'] = true, ['collaboration'] = true, ['date'] = true, ['df'] = true, ['display-authors'] = true, ['first'] = true, ['given'] = true, ['language'] = true, ['last'] = true, ['mode'] = true, ['name-list-style'] = true, ['no-tracking'] = true, ['p'] = true, ['page'] = true, ['pages'] = true, ['postscript'] = true, ['pp'] = true, ['quotation'] = true, ['quote'] = true, ['ref'] = true, ['surname'] = true, ['template-doc-demo'] = true, ['title'] = true, ['trans-title'] = true, ['vauthors'] = true, ['year'] = true, } local limited_numbered_arguments = { ['author#'] = true, ['author-first#'] = true, ['author#-first'] = true, ['author-given#'] = true, ['author#-given'] = true, ['author-last#'] = true, ['author#-last'] = true, ['author-surname#'] = true, ['author#-surname'] = true, ['author-link#'] = true, ['author#-link'] = true, ['authorlink#'] = true, ['author#link'] = true, ['author-mask#'] = true, ['author#-mask'] = true, ['first#'] = true, ['given#'] = true, ['last#'] = true, ['surname#'] = true, } --[[--------------------------< U N I Q U E _ A R G U M E N T S >---------------------------------------------- Some templates have unique parameters. Those templates and their unique parameters are listed here. Keys in this table are the template's CitationClass parameter value Same conventions for true/false/tracked/nil as above. ]] local unique_arguments = { ['audio-visual'] = { ['transcript'] = true, ['transcript-format'] = true, ['transcript-url'] = true, }, conference = { ['book-title'] = true, ['conference'] = true, ['conference-format'] = true, ['conference-url'] = true, ['event'] = true, }, episode = { ['airdate'] = true, ['air-date'] = true, ['credits'] = true, ['episode-link'] = true, -- alias of |title-link= ['network'] = true, ['season'] = true, ['series-link'] = true, ['series-no'] = true, ['series-number'] = true, ['station'] = true, ['transcript'] = true, ['transcript-format'] = true, ['transcripturl'] = false, ['transcript-url'] = true, }, mailinglist = { ['mailing-list'] = true, }, map = { ['cartography'] = true, ['inset'] = true, ['map'] = true, ['map-format'] = true, ['map-url'] = true, ['map-url-access'] = true, ['script-map'] = true, ['sections'] = true, ['sheet'] = true, ['sheets'] = true, ['trans-map'] = true, }, newsgroup = { ['message-id'] = true, ['newsgroup'] = true, }, report = { ['docket'] = true, }, serial = { ['airdate'] = true, ['air-date'] = true, ['credits'] = true, ['episode'] = true, -- cite serial only TODO: make available to cite episode? ['episode-link'] = true, -- alias of |title-link= ['network'] = true, ['series-link'] = true, ['station'] = true, }, speech = { ['conference'] = true, ['conference-format'] = true, ['conference-url'] = true, ['event'] = true, }, thesis = { ['degree'] = true, ['docket'] = true, }, } --[[--------------------------< T E M P L A T E _ L I S T _ G E T >-------------------------------------------- gets a list of the templates from table t ]] local function template_list_get (t) local out = {}; -- a table for output for k, _ in pairs (t) do -- spin through the table and collect the keys table.insert (out, k) -- add each key to the output table end return out; -- and done end --[[--------------------------< E X P O R T E D T A B L E S >------------------------------------------------ ]] return { basic_arguments = basic_arguments, numbered_arguments = numbered_arguments, limited_basic_arguments = limited_basic_arguments, limited_numbered_arguments = limited_numbered_arguments, preprint_arguments = preprint_arguments, preprint_template_list = template_list_get (preprint_arguments), -- make a template list from preprint_arguments{} table unique_arguments = unique_arguments, unique_param_template_list = template_list_get (unique_arguments), -- make a template list from unique_arguments{} table }; 6773846564c816e7f9eae451b65436cbda849bc5 Module:TableTools 828 73 161 2022-01-31T13:08:18Z Canopus >MSGJ 0 updates/fixes requested by [[User:Uzume]] Scribunto text/plain ------------------------------------------------------------------------------------ -- TableTools -- -- -- -- This module includes a number of functions for dealing with Lua tables. -- -- It is a meta-module, meant to be called from other Lua modules, and should not -- -- be called directly from #invoke. -- ------------------------------------------------------------------------------------ local libraryUtil = require('libraryUtil') local p = {} -- Define often-used variables and functions. local floor = math.floor local infinity = math.huge local checkType = libraryUtil.checkType local checkTypeMulti = libraryUtil.checkTypeMulti ------------------------------------------------------------------------------------ -- isPositiveInteger -- -- This function returns true if the given value is a positive integer, and false -- if not. Although it doesn't operate on tables, it is included here as it is -- useful for determining whether a given table key is in the array part or the -- hash part of a table. ------------------------------------------------------------------------------------ function p.isPositiveInteger(v) return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity end ------------------------------------------------------------------------------------ -- isNan -- -- This function returns true if the given number is a NaN value, and false if -- not. Although it doesn't operate on tables, it is included here as it is useful -- for determining whether a value can be a valid table key. Lua will generate an -- error if a NaN is used as a table key. ------------------------------------------------------------------------------------ function p.isNan(v) return type(v) == 'number' and v ~= v end ------------------------------------------------------------------------------------ -- shallowClone -- -- This returns a clone of a table. The value returned is a new table, but all -- subtables and functions are shared. Metamethods are respected, but the returned -- table will have no metatable of its own. ------------------------------------------------------------------------------------ function p.shallowClone(t) checkType('shallowClone', 1, t, 'table') local ret = {} for k, v in pairs(t) do ret[k] = v end return ret end ------------------------------------------------------------------------------------ -- removeDuplicates -- -- This removes duplicate values from an array. Non-positive-integer keys are -- ignored. The earliest value is kept, and all subsequent duplicate values are -- removed, but otherwise the array order is unchanged. ------------------------------------------------------------------------------------ function p.removeDuplicates(arr) checkType('removeDuplicates', 1, arr, 'table') local isNan = p.isNan local ret, exists = {}, {} for _, v in ipairs(arr) do if isNan(v) then -- NaNs can't be table keys, and they are also unique, so we don't need to check existence. ret[#ret + 1] = v else if not exists[v] then ret[#ret + 1] = v exists[v] = true end end end return ret end ------------------------------------------------------------------------------------ -- numKeys -- -- This takes a table and returns an array containing the numbers of any numerical -- keys that have non-nil values, sorted in numerical order. ------------------------------------------------------------------------------------ function p.numKeys(t) checkType('numKeys', 1, t, 'table') local isPositiveInteger = p.isPositiveInteger local nums = {} for k in pairs(t) do if isPositiveInteger(k) then nums[#nums + 1] = k end end table.sort(nums) return nums end ------------------------------------------------------------------------------------ -- affixNums -- -- This takes a table and returns an array containing the numbers of keys with the -- specified prefix and suffix. For example, for the table -- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will return -- {1, 3, 6}. ------------------------------------------------------------------------------------ function p.affixNums(t, prefix, suffix) checkType('affixNums', 1, t, 'table') checkType('affixNums', 2, prefix, 'string', true) checkType('affixNums', 3, suffix, 'string', true) local function cleanPattern(s) -- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally. return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1') end prefix = prefix or '' suffix = suffix or '' prefix = cleanPattern(prefix) suffix = cleanPattern(suffix) local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$' local nums = {} for k in pairs(t) do if type(k) == 'string' then local num = mw.ustring.match(k, pattern) if num then nums[#nums + 1] = tonumber(num) end end end table.sort(nums) return nums end ------------------------------------------------------------------------------------ -- numData -- -- Given a table with keys like {"foo1", "bar1", "foo2", "baz2"}, returns a table -- of subtables in the format -- {[1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'}}. -- Keys that don't end with an integer are stored in a subtable named "other". The -- compress option compresses the table so that it can be iterated over with -- ipairs. ------------------------------------------------------------------------------------ function p.numData(t, compress) checkType('numData', 1, t, 'table') checkType('numData', 2, compress, 'boolean', true) local ret = {} for k, v in pairs(t) do local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$') if num then num = tonumber(num) local subtable = ret[num] or {} if prefix == '' then -- Positional parameters match the blank string; put them at the start of the subtable instead. prefix = 1 end subtable[prefix] = v ret[num] = subtable else local subtable = ret.other or {} subtable[k] = v ret.other = subtable end end if compress then local other = ret.other ret = p.compressSparseArray(ret) ret.other = other end return ret end ------------------------------------------------------------------------------------ -- compressSparseArray -- -- This takes an array with one or more nil values, and removes the nil values -- while preserving the order, so that the array can be safely traversed with -- ipairs. ------------------------------------------------------------------------------------ function p.compressSparseArray(t) checkType('compressSparseArray', 1, t, 'table') local ret = {} local nums = p.numKeys(t) for _, num in ipairs(nums) do ret[#ret + 1] = t[num] end return ret end ------------------------------------------------------------------------------------ -- sparseIpairs -- -- This is an iterator for sparse arrays. It can be used like ipairs, but can -- handle nil values. ------------------------------------------------------------------------------------ function p.sparseIpairs(t) checkType('sparseIpairs', 1, t, 'table') local nums = p.numKeys(t) local i = 0 local lim = #nums return function () i = i + 1 if i <= lim then local key = nums[i] return key, t[key] else return nil, nil end end end ------------------------------------------------------------------------------------ -- size -- -- This returns the size of a key/value pair table. It will also work on arrays, -- but for arrays it is more efficient to use the # operator. ------------------------------------------------------------------------------------ function p.size(t) checkType('size', 1, t, 'table') local i = 0 for _ in pairs(t) do i = i + 1 end return i end local function defaultKeySort(item1, item2) -- "number" < "string", so numbers will be sorted before strings. local type1, type2 = type(item1), type(item2) if type1 ~= type2 then return type1 < type2 elseif type1 == 'table' or type1 == 'boolean' or type1 == 'function' then return tostring(item1) < tostring(item2) else return item1 < item2 end end ------------------------------------------------------------------------------------ -- keysToList -- -- Returns an array of the keys in a table, sorted using either a default -- comparison function or a custom keySort function. ------------------------------------------------------------------------------------ function p.keysToList(t, keySort, checked) if not checked then checkType('keysToList', 1, t, 'table') checkTypeMulti('keysToList', 2, keySort, {'function', 'boolean', 'nil'}) end local arr = {} local index = 1 for k in pairs(t) do arr[index] = k index = index + 1 end if keySort ~= false then keySort = type(keySort) == 'function' and keySort or defaultKeySort table.sort(arr, keySort) end return arr end ------------------------------------------------------------------------------------ -- sortedPairs -- -- Iterates through a table, with the keys sorted using the keysToList function. -- If there are only numerical keys, sparseIpairs is probably more efficient. ------------------------------------------------------------------------------------ function p.sortedPairs(t, keySort) checkType('sortedPairs', 1, t, 'table') checkType('sortedPairs', 2, keySort, 'function', true) local arr = p.keysToList(t, keySort, true) local i = 0 return function () i = i + 1 local key = arr[i] if key ~= nil then return key, t[key] else return nil, nil end end end ------------------------------------------------------------------------------------ -- isArray -- -- Returns true if the given value is a table and all keys are consecutive -- integers starting at 1. ------------------------------------------------------------------------------------ function p.isArray(v) if type(v) ~= 'table' then return false end local i = 0 for _ in pairs(v) do i = i + 1 if v[i] == nil then return false end end return true end ------------------------------------------------------------------------------------ -- isArrayLike -- -- Returns true if the given value is iterable and all keys are consecutive -- integers starting at 1. ------------------------------------------------------------------------------------ function p.isArrayLike(v) if not pcall(pairs, v) then return false end local i = 0 for _ in pairs(v) do i = i + 1 if v[i] == nil then return false end end return true end ------------------------------------------------------------------------------------ -- invert -- -- Transposes the keys and values in an array. For example, {"a", "b", "c"} -> -- {a = 1, b = 2, c = 3}. Duplicates are not supported (result values refer to -- the index of the last duplicate) and NaN values are ignored. ------------------------------------------------------------------------------------ function p.invert(arr) checkType("invert", 1, arr, "table") local isNan = p.isNan local map = {} for i, v in ipairs(arr) do if not isNan(v) then map[v] = i end end return map end ------------------------------------------------------------------------------------ -- listToSet -- -- Creates a set from the array part of the table. Indexing the set by any of the -- values of the array returns true. For example, {"a", "b", "c"} -> -- {a = true, b = true, c = true}. NaN values are ignored as Lua considers them -- never equal to any value (including other NaNs or even themselves). ------------------------------------------------------------------------------------ function p.listToSet(arr) checkType("listToSet", 1, arr, "table") local isNan = p.isNan local set = {} for _, v in ipairs(arr) do if not isNan(v) then set[v] = true end end return set end ------------------------------------------------------------------------------------ -- deepCopy -- -- Recursive deep copy function. Preserves identities of subtables. ------------------------------------------------------------------------------------ local function _deepCopy(orig, includeMetatable, already_seen) -- Stores copies of tables indexed by the original table. already_seen = already_seen or {} local copy = already_seen[orig] if copy ~= nil then return copy end if type(orig) == 'table' then copy = {} for orig_key, orig_value in pairs(orig) do copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen) end already_seen[orig] = copy if includeMetatable then local mt = getmetatable(orig) if mt ~= nil then local mt_copy = _deepCopy(mt, includeMetatable, already_seen) setmetatable(copy, mt_copy) already_seen[mt] = mt_copy end end else -- number, string, boolean, etc copy = orig end return copy end function p.deepCopy(orig, noMetatable, already_seen) checkType("deepCopy", 3, already_seen, "table", true) return _deepCopy(orig, not noMetatable, already_seen) end ------------------------------------------------------------------------------------ -- sparseConcat -- -- Concatenates all values in the table that are indexed by a number, in order. -- sparseConcat{a, nil, c, d} => "acd" -- sparseConcat{nil, b, c, d} => "bcd" ------------------------------------------------------------------------------------ function p.sparseConcat(t, sep, i, j) local arr = {} local arr_i = 0 for _, v in p.sparseIpairs(t) do arr_i = arr_i + 1 arr[arr_i] = v end return table.concat(arr, sep, i, j) end ------------------------------------------------------------------------------------ -- length -- -- Finds the length of an array, or of a quasi-array with keys such as "data1", -- "data2", etc., using an exponential search algorithm. It is similar to the -- operator #, but may return a different value when there are gaps in the array -- portion of the table. Intended to be used on data loaded with mw.loadData. For -- other tables, use #. -- Note: #frame.args in frame object always be set to 0, regardless of the number -- of unnamed template parameters, so use this function for frame.args. ------------------------------------------------------------------------------------ function p.length(t, prefix) -- requiring module inline so that [[Module:Exponential search]] which is -- only needed by this one function doesn't get millions of transclusions local expSearch = require("Module:Exponential search") checkType('length', 1, t, 'table') checkType('length', 2, prefix, 'string', true) return expSearch(function (i) local key if prefix then key = prefix .. tostring(i) else key = i end return t[key] ~= nil end) or 0 end ------------------------------------------------------------------------------------ -- inArray -- -- Returns true if valueToFind is a member of the array, and false otherwise. ------------------------------------------------------------------------------------ function p.inArray(arr, valueToFind) checkType("inArray", 1, arr, "table") -- if valueToFind is nil, error? for _, v in ipairs(arr) do if v == valueToFind then return true end end return false end return p 085e7094ac84eb0132ee65822cf3f69cd8ba3d81 Template:Short description/lowercasecheck 10 67 149 2022-02-12T16:35:05Z Canopus >ToBeFree 0 Changed protection settings for "[[Template:Short description/lowercasecheck]]": 4 million transclusions, through [[Template:Short description]] ([[WP:HRT]]) ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite)) wikitext text/x-wiki {{#ifeq:<!--test first character for lower-case letter-->{{#invoke:string|find|1={{{1|}}}|2=^%l|plain=false}}|1 |<!-- first character is a lower case letter; test against whitelist -->{{#switch: {{First word|{{{1|}}}}}<!--begin whitelist--> |c. <!--for circa--> |gTLD |iMac |iOS |iOS, |iPad |iPhone |iTunes |macOS |none |pH |pH-dependent=<!-- end whitelist; short description starts with an allowed lower-case string; whitelist matched; do nothing --> |#default=<!-- apply category to track lower-case short descriptions -->{{main other|[[Category:Pages with lower-case short description|{{trim|{{{1|}}}}}]]}}{{Testcases other|{{red|CATEGORY APPLIED}}}}<!-- end whitelist test -->}} |<!-- short description does not start with lower-case letter; do nothing; end lower-case test --> }}<noinclude> {{documentation}} </noinclude> 9a6d4db14b74614625fd234b4f8ee3c8e1a235c0 Module:Convert 828 46 107 2022-02-13T04:01:13Z Canopus >Johnuniq 0 update from sandbox per [[Template talk:Convert#Module version 27]] Scribunto text/plain -- Convert a value from one unit of measurement to another. -- Example: {{convert|123|lb|kg}} --> 123 pounds (56 kg) -- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki. local MINUS = '−' -- Unicode U+2212 MINUS SIGN (UTF-8: e2 88 92) local abs = math.abs local floor = math.floor local format = string.format local log10 = math.log10 local ustring = mw.ustring local ulen = ustring.len local usub = ustring.sub -- Configuration options to keep magic values in one location. -- Conversion data and message text are defined in separate modules. local config, maxsigfig local numdot -- must be '.' or ',' or a character which works in a regex local numsep, numsep_remove, numsep_remove2 local data_code, all_units local text_code local varname -- can be a code to use variable names that depend on value local from_en_table -- to translate an output string of en digits to local language local to_en_table -- to translate an input string of digits in local language to en -- Use translation_table in convert/text to change the following. local en_default -- true uses lang=en unless convert has lang=local or local digits local group_method = 3 -- code for how many digits are in a group local per_word = 'per' -- for units like "liters per kilometer" local plural_suffix = 's' -- only other useful value is probably '' to disable plural unit names local omitsep -- true to omit separator before local symbol/name -- All units should be defined in the data module. However, to cater for quick changes -- and experiments, any unknown unit is looked up in an extra data module, if it exists. -- That module would be transcluded in only a small number of pages, so there should be -- little server overhead from making changes, and changes should propagate quickly. local extra_module -- name of module with extra units local extra_units -- nil or table of extra units from extra_module -- Some options in the invoking template can set variables used later in the module. local currency_text -- for a user-defined currency symbol: {{convert|12|$/ha|$=€}} (euro replaces dollar) local function from_en(text) -- Input is a string representing a number in en digits with '.' decimal mark, -- without digit grouping (which is done just after calling this). -- Return the translation of the string with numdot and digits in local language. if numdot ~= '.' then text = text:gsub('%.', numdot) end if from_en_table then text = text:gsub('%d', from_en_table) end return text end local function to_en(text) -- Input is a string representing a number in the local language with -- an optional numdot decimal mark and numsep digit grouping. -- Return the translation of the string with '.' mark and en digits, -- and no separators (they have to be removed here to handle cases like -- numsep = '.' and numdot = ',' with input "1.234.567,8"). if to_en_table then text = ustring.gsub(text, '%d', to_en_table) end if numsep_remove then text = text:gsub(numsep_remove, '') end if numsep_remove2 then text = text:gsub(numsep_remove2, '') end if numdot ~= '.' then text = text:gsub(numdot, '.') end return text end local function decimal_mark(text) -- Return ',' if text probably is using comma for decimal mark, or has no decimal mark. -- Return '.' if text probably is using dot for decimal mark. -- Otherwise return nothing (decimal mark not known). if not text:find('[.,]') then return ',' end text = text:gsub('^%-', ''):gsub('%+%d+/%d+$', ''):gsub('[Ee]%-?%d+$', '') local decimal = text:match('^0?([.,])%d+$') or text:match('%d([.,])%d?%d?$') or text:match('%d([.,])%d%d%d%d+$') if decimal then return decimal end if text:match('%.%d+%.') then return ',' end if text:match('%,%d+,') then return '.' end end local add_warning, with_separator -- forward declarations local function to_en_with_check(text, parms) -- Version of to_en() for a wiki using numdot = ',' and numsep = '.' to check -- text (an input number as a string) which might have been copied from enwiki. -- For example, in '1.234' the '.' could be a decimal mark or a group separator. -- From viwiki. if to_en_table then text = ustring.gsub(text, '%d', to_en_table) end if decimal_mark(text) == '.' then local original = text text = text:gsub(',', '') -- for example, interpret "1,234.5" as an enwiki value if parms then add_warning(parms, 0, 'cvt_enwiki_num', original, with_separator({}, text)) end else if numsep_remove then text = text:gsub(numsep_remove, '') end if numsep_remove2 then text = text:gsub(numsep_remove2, '') end if numdot ~= '.' then text = text:gsub(numdot, '.') end end return text end local function omit_separator(id) -- Return true if there should be no separator before id (a unit symbol or name). -- For zhwiki, there should be no separator if id uses local characters. -- The following kludge should be a sufficient test. if omitsep then if id:sub(1, 2) == '-{' then -- for "-{...}-" content language variant return true end if id:byte() > 127 then local first = usub(id, 1, 1) if first ~= 'Å' and first ~= '°' and first ~= 'µ' then return true end end end return id:sub(1, 1) == '/' -- no separator before units like "/ha" end local spell_module -- name of module that can spell numbers local speller -- function from that module to handle spelling (set if needed) local wikidata_module, wikidata_data_module -- names of Wikidata modules local wikidata_code, wikidata_data -- exported tables from those modules (set if needed) local function set_config(args) -- Set configuration options from template #invoke or defaults. config = args maxsigfig = config.maxsigfig or 14 -- maximum number of significant figures local data_module, text_module local sandbox = config.sandbox and ('/' .. config.sandbox) or '' data_module = "Module:Convert/data" .. sandbox text_module = "Module:Convert/text" .. sandbox extra_module = "Module:Convert/extra" .. sandbox wikidata_module = "Module:Convert/wikidata" .. sandbox wikidata_data_module = "Module:Convert/wikidata/data" .. sandbox spell_module = "Module:ConvertNumeric" data_code = mw.loadData(data_module) text_code = mw.loadData(text_module) all_units = data_code.all_units local translation = text_code.translation_table if translation then numdot = translation.numdot numsep = translation.numsep if numdot == ',' and numsep == '.' then if text_code.all_messages.cvt_enwiki_num then to_en = to_en_with_check end end if translation.group then group_method = translation.group end if translation.per_word then per_word = translation.per_word end if translation.plural_suffix then plural_suffix = translation.plural_suffix end varname = translation.varname from_en_table = translation.from_en local use_workaround = true if use_workaround then -- 2013-07-05 workaround bug by making a copy of the required table. -- mw.ustring.gsub fails with a table (to_en_table) as the replacement, -- if the table is accessed via mw.loadData. local source = translation.to_en if source then to_en_table = {} for k, v in pairs(source) do to_en_table[k] = v end end else to_en_table = translation.to_en end if translation.lang == 'en default' then en_default = true -- for hiwiki end omitsep = translation.omitsep -- for zhwiki end numdot = config.numdot or numdot or '.' -- decimal mark before fractional digits numsep = config.numsep or numsep or ',' -- group separator for numbers -- numsep should be ',' or '.' or '' or '&nbsp;' or a Unicode character. -- numsep_remove must work in a regex to identify separators to be removed. if numsep ~= '' then numsep_remove = (numsep == '.') and '%.' or numsep end if numsep ~= ',' and numdot ~= ',' then numsep_remove2 = ',' -- so numbers copied from enwiki will work end end local function collection() -- Return a table to hold items. return { n = 0, add = function (self, item) self.n = self.n + 1 self[self.n] = item end, } end local function divide(numerator, denominator) -- Return integers quotient, remainder resulting from dividing the two -- given numbers, which should be unsigned integers. local quotient, remainder = floor(numerator / denominator), numerator % denominator if not (0 <= remainder and remainder < denominator) then -- Floating point limits may need this, as in {{convert|160.02|Ym|ydftin}}. remainder = 0 end return quotient, remainder end local function split(text, delimiter) -- Return a numbered table with fields from splitting text. -- The delimiter is used in a regex without escaping (for example, '.' would fail). -- Each field has any leading/trailing whitespace removed. local t = {} text = text .. delimiter -- to get last item for item in text:gmatch('%s*(.-)%s*' .. delimiter) do table.insert(t, item) end return t end local function strip(text) -- If text is a string, return its content with no leading/trailing -- whitespace. Otherwise return nil (a nil argument gives a nil result). if type(text) == 'string' then return text:match("^%s*(.-)%s*$") end end local function table_len(t) -- Return length (<100) of a numbered table to replace #t which is -- documented to not work if t is accessed via mw.loadData(). for i = 1, 100 do if t[i] == nil then return i - 1 end end end local function wanted_category(catkey, catsort, want_warning) -- Return message category if it is wanted in current namespace, -- otherwise return ''. local cat local title = mw.title.getCurrentTitle() if title then local nsdefault = '0' -- default namespace: '0' = article; '0,10' = article and template local namespace = title.namespace for _, v in ipairs(split(config.nscat or nsdefault, ',')) do if namespace == tonumber(v) then cat = text_code.all_categories[want_warning and 'warning' or catkey] if catsort and catsort ~= '' and cat:sub(-2) == ']]' then cat = cat:sub(1, -3) .. '|' .. mw.text.nowiki(usub(catsort, 1, 20)) .. ']]' end break end end end return cat or '' end local function message(parms, mcode, is_warning) -- Return wikitext for an error message, including category if specified -- for the message type. -- mcode = numbered table specifying the message: -- mcode[1] = 'cvt_xxx' (string used as a key to get message info) -- mcode[2] = 'parm1' (string to replace '$1' if any in message) -- mcode[3] = 'parm2' (string to replace '$2' if any in message) -- mcode[4] = 'parm3' (string to replace '$3' if any in message) local msg if type(mcode) == 'table' then if mcode[1] == 'cvt_no_output' then -- Some errors should cause convert to output an empty string, -- for example, for an optional field in an infobox. return '' end msg = text_code.all_messages[mcode[1]] end parms.have_problem = true local function subparm(fmt, ...) local rep = {} for i, v in ipairs({...}) do rep['$' .. i] = v end return (fmt:gsub('$%d+', rep)) end if msg then local parts = {} local regex, replace = msg.regex, msg.replace for i = 1, 3 do local limit = 40 local s = mcode[i + 1] if s then if regex and replace then s = s:gsub(regex, replace) limit = nil -- allow long "should be" messages end -- Escape user input so it does not break the message. -- To avoid tags (like {{convert|1<math>23</math>|m}}) breaking -- the mouseover title, any strip marker starting with char(127) is -- replaced with '...' (text not needing i18n). local append local pos = s:find(string.char(127), 1, true) if pos then append = '...' s = s:sub(1, pos - 1) end if limit and ulen(s) > limit then s = usub(s, 1, limit) append = '...' end s = mw.text.nowiki(s) .. (append or '') else s = '?' end parts['$' .. i] = s end local function ispreview() -- Return true if a prominent message should be shown. if parms.test == 'preview' or parms.test == 'nopreview' then -- For testing, can preview a real message or simulate a preview -- when running automated tests. return parms.test == 'preview' end local success, revid = pcall(function () return (parms.frame):preprocess('{{REVISIONID}}') end) return success and (revid == '') end local want_warning = is_warning and not config.warnings and -- show unobtrusive warnings if config.warnings not configured not msg.nowarn -- but use msg settings, not standard warning, if specified local title = string.gsub(msg[1] or 'Missing message', '$%d+', parts) local text = want_warning and '*' or msg[2] or 'Missing message' local cat = wanted_category(msg[3], mcode[2], want_warning) local anchor = msg[4] or '' local fmtkey = ispreview() and 'cvt_format_preview' or (want_warning and 'cvt_format2' or msg.format or 'cvt_format') local fmt = text_code.all_messages[fmtkey] or 'convert: bug' return subparm(fmt, title:gsub('"', '&quot;'), text, cat, anchor) end return 'Convert internal error: unknown message' end function add_warning(parms, level, key, text1, text2) -- for forward declaration above -- If enabled, add a warning that will be displayed after the convert result. -- A higher level is more verbose: more kinds of warnings are displayed. -- To reduce output noise, only the first warning is displayed. if level <= (tonumber(config.warnings) or 1) then if parms.warnings == nil then parms.warnings = message(parms, { key, text1, text2 }, true) end end end local function spell_number(parms, inout, number, numerator, denominator) -- Return result of spelling (number, numerator, denominator), or -- return nil if spelling is not available or not supported for given text. -- Examples (each value must be a string or nil): -- number numerator denominator output -- ------ --------- ----------- ------------------- -- "1.23" nil nil one point two three -- "1" "2" "3" one and two thirds -- nil "2" "3" two thirds if not speller then local function get_speller(module) return require(module).spell_number end local success success, speller = pcall(get_speller, spell_module) if not success or type(speller) ~= 'function' then add_warning(parms, 1, 'cvt_no_spell', 'spell') return nil end end local case if parms.spell_upper == inout then case = true parms.spell_upper = nil -- only uppercase first word in a multiple unit end local sp = not parms.opt_sp_us local adj = parms.opt_adjectival return speller(number, numerator, denominator, case, sp, adj) end ------------------------------------------------------------------------ -- BEGIN: Code required only for built-in units. -- LATER: If need much more code, move to another module to simplify this module. local function speed_of_sound(altitude) -- This is for the Mach built-in unit of speed. -- Return speed of sound in metres per second at given altitude in feet. -- If no altitude given, use default (zero altitude = sea level). -- Table gives speed of sound in miles per hour at various altitudes: -- altitude = -17,499 to 402,499 feet -- mach_table[a + 4] = s where -- a = (altitude / 5000) rounded to nearest integer (-3 to 80) -- s = speed of sound (mph) at that altitude -- LATER: Should calculate result from an interpolation between the next -- lower and higher altitudes in table, rather than rounding to nearest. -- From: http://www.aerospaceweb.org/question/atmosphere/q0112.shtml local mach_table = { -- a = 799.5, 787.0, 774.2, 761.207051, -- -3 to 0 748.0, 734.6, 721.0, 707.0, 692.8, 678.3, 663.5, 660.1, 660.1, 660.1, -- 1 to 10 660.1, 660.1, 660.1, 662.0, 664.3, 666.5, 668.9, 671.1, 673.4, 675.6, -- 11 to 20 677.9, 683.7, 689.9, 696.0, 702.1, 708.1, 714.0, 719.9, 725.8, 731.6, -- 21 to 30 737.3, 737.7, 737.7, 736.2, 730.5, 724.6, 718.8, 712.9, 707.0, 701.0, -- 31 to 40 695.0, 688.9, 682.8, 676.6, 670.4, 664.1, 657.8, 652.9, 648.3, 643.7, -- 41 to 50 639.1, 634.4, 629.6, 624.8, 620.0, 615.2, 613.2, 613.2, 613.2, 613.5, -- 51 to 60 614.4, 615.3, 616.7, 619.8, 623.4, 629.7, 635.0, 641.1, 650.6, 660.0, -- 61 to 70 672.5, 674.3, 676.1, 677.9, 679.7, 681.5, 683.3, 685.1, 686.8, 688.6, -- 71 to 80 } altitude = altitude or 0 local a = (altitude < 0) and -altitude or altitude a = floor(a / 5000 + 0.5) if altitude < 0 then a = -a end if a < -3 then a = -3 elseif a > 80 then a = 80 end return mach_table[a + 4] * 0.44704 -- mph converted to m/s end -- END: Code required only for built-in units. ------------------------------------------------------------------------ local function add_style(parms, class) -- Add selected template style to parms if not already present. parms.templatestyles = parms.templatestyles or {} if not parms.templatestyles[class] then parms.templatestyles[class] = parms.frame:extensionTag({ name = 'templatestyles', args = { src = text_code.titles[class] } }) end end local function get_styles(parms) -- Return string of required template styles, empty if none. if parms.templatestyles then local t = {} for _, v in pairs(parms.templatestyles) do table.insert(t, v) end return table.concat(t) end return '' end local function get_range(word) -- Return a range (string or table) corresponding to word (like "to"), -- or return nil if not a range word. local ranges = text_code.ranges return ranges.types[word] or ranges.types[ranges.aliases[word]] end local function check_mismatch(unit1, unit2) -- If unit1 cannot be converted to unit2, return an error message table. -- This allows conversion between units of the same type, and between -- Nm (normally torque) and ftlb (energy), as in gun-related articles. -- This works because Nm is the base unit (scale = 1) for both the -- primary type (torque), and the alternate type (energy, where Nm = J). -- A match occurs if the primary types are the same, or if unit1 matches -- the alternate type of unit2, and vice versa. That provides a whitelist -- of which conversions are permitted between normally incompatible types. if unit1.utype == unit2.utype or (unit1.utype == unit2.alttype and unit1.alttype == unit2.utype) then return nil end return { 'cvt_mismatch', unit1.utype, unit2.utype } end local function override_from(out_table, in_table, fields) -- Copy the specified fields from in_table to out_table, but do not -- copy nil fields (keep any corresponding field in out_table). for _, field in ipairs(fields) do if in_table[field] then out_table[field] = in_table[field] end end end local function shallow_copy(t) -- Return a shallow copy of table t. -- Do not need the features and overhead of the Scribunto mw.clone(). local result = {} for k, v in pairs(t) do result[k] = v end return result end local unit_mt = { -- Metatable to get missing values for a unit that does not accept SI prefixes. -- Warning: The boolean value 'false' is returned for any missing field -- so __index is not called twice for the same field in a given unit. __index = function (self, key) local value if key == 'name1' or key == 'sym_us' then value = self.symbol elseif key == 'name2' then value = self.name1 .. plural_suffix elseif key == 'name1_us' then value = self.name1 if not rawget(self, 'name2_us') then -- If name1_us is 'foot', do not make name2_us by appending plural_suffix. self.name2_us = self.name2 end elseif key == 'name2_us' then local raw1_us = rawget(self, 'name1_us') if raw1_us then value = raw1_us .. plural_suffix else value = self.name2 end elseif key == 'link' then value = self.name1 else value = false end rawset(self, key, value) return value end } local function prefixed_name(unit, name, index) -- Return unit name with SI prefix inserted at correct position. -- index = 1 (name1), 2 (name2), 3 (name1_us), 4 (name2_us). -- The position is a byte (not character) index, so use Lua's sub(). local pos = rawget(unit, 'prefix_position') if type(pos) == 'string' then pos = tonumber(split(pos, ',')[index]) end if pos then return name:sub(1, pos - 1) .. unit.si_name .. name:sub(pos) end return unit.si_name .. name end local unit_prefixed_mt = { -- Metatable to get missing values for a unit that accepts SI prefixes. -- Before use, fields si_name, si_prefix must be defined. -- The unit must define _symbol, _name1 and -- may define _sym_us, _name1_us, _name2_us -- (_sym_us, _name2_us may be defined for a language using sp=us -- to refer to a variant unrelated to U.S. units). __index = function (self, key) local value if key == 'symbol' then value = self.si_prefix .. self._symbol elseif key == 'sym_us' then value = rawget(self, '_sym_us') if value then value = self.si_prefix .. value else value = self.symbol end elseif key == 'name1' then value = prefixed_name(self, self._name1, 1) elseif key == 'name2' then value = rawget(self, '_name2') if value then value = prefixed_name(self, value, 2) else value = self.name1 .. plural_suffix end elseif key == 'name1_us' then value = rawget(self, '_name1_us') if value then value = prefixed_name(self, value, 3) else value = self.name1 end elseif key == 'name2_us' then value = rawget(self, '_name2_us') if value then value = prefixed_name(self, value, 4) elseif rawget(self, '_name1_us') then value = self.name1_us .. plural_suffix else value = self.name2 end elseif key == 'link' then value = self.name1 else value = false end rawset(self, key, value) return value end } local unit_per_mt = { -- Metatable to get values for a per unit of form "x/y". -- This is never called to determine a unit name or link because per units -- are handled as a special case. -- Similarly, the default output is handled elsewhere, and for a symbol -- this is only called from get_default() for default_exceptions. __index = function (self, key) local value if key == 'symbol' then local per = self.per local unit1, unit2 = per[1], per[2] if unit1 then value = unit1[key] .. '/' .. unit2[key] else value = '/' .. unit2[key] end elseif key == 'sym_us' then value = self.symbol elseif key == 'scale' then local per = self.per local unit1, unit2 = per[1], per[2] value = (unit1 and unit1.scale or 1) * self.scalemultiplier / unit2.scale else value = false end rawset(self, key, value) return value end } local function make_per(unitcode, unit_table, ulookup) -- Return true, t where t is a per unit with unit codes expanded to unit tables, -- or return false, t where t is an error message table. local result = { unitcode = unitcode, utype = unit_table.utype, per = {} } override_from(result, unit_table, { 'invert', 'iscomplex', 'default', 'link', 'symbol', 'symlink' }) result.symbol_raw = (result.symbol or false) -- to distinguish between a defined exception and a metatable calculation local prefix for i, v in ipairs(unit_table.per) do if i == 1 and v == '' then -- First unit symbol can be empty; that gives a nil first unit table. elseif i == 1 and text_code.currency[v] then prefix = currency_text or v else local success, t = ulookup(v) if not success then return false, t end result.per[i] = t end end local multiplier = unit_table.multiplier if not result.utype then -- Creating an automatic per unit. local unit1 = result.per[1] local utype = (unit1 and unit1.utype or prefix or '') .. '/' .. result.per[2].utype local t = data_code.per_unit_fixups[utype] if t then if type(t) == 'table' then utype = t.utype or utype result.link = result.link or t.link multiplier = multiplier or t.multiplier else utype = t end end result.utype = utype end result.scalemultiplier = multiplier or 1 result.vprefix = prefix or false -- set to non-nil to avoid calling __index return true, setmetatable(result, unit_per_mt) end local function lookup(parms, unitcode, what, utable, fails, depth) -- Return true, t where t is a copy of the unit's converter table, -- or return false, t where t is an error message table. -- Parameter 'what' determines whether combination units are accepted: -- 'no_combination' : single unit only -- 'any_combination' : single unit or combination or output multiple -- 'only_multiple' : single unit or output multiple only -- Parameter unitcode is a symbol (like 'g'), with an optional SI prefix (like 'kg'). -- If, for example, 'kg' is in this table, that entry is used; -- otherwise the prefix ('k') is applied to the base unit ('g'). -- If unitcode is a known combination code (and if allowed by what), -- a table of output multiple unit tables is included in the result. -- For compatibility with the old template, an underscore in a unitcode is -- replaced with a space so usage like {{convert|350|board_feet}} works. -- Wikignomes may also put two spaces or "&nbsp;" in combinations, so -- replace underscore, "&nbsp;", and multiple spaces with a single space. utable = utable or parms.unittable or all_units fails = fails or {} depth = depth and depth + 1 or 1 if depth > 9 then -- There are ways to mistakenly define units which result in infinite -- recursion when lookup() is called. That gives a long delay and very -- confusing error messages, so the depth parameter is used as a guard. return false, { 'cvt_lookup', unitcode } end if unitcode == nil or unitcode == '' then return false, { 'cvt_no_unit' } end unitcode = unitcode:gsub('_', ' '):gsub('&nbsp;', ' '):gsub(' +', ' ') local function call_make_per(t) return make_per(unitcode, t, function (ucode) return lookup(parms, ucode, 'no_combination', utable, fails, depth) end ) end local t = utable[unitcode] if t then if t.shouldbe then return false, { 'cvt_should_be', t.shouldbe } end if t.sp_us then parms.opt_sp_us = true end local target = t.target -- nil, or unitcode is an alias for this target if target then local success, result = lookup(parms, target, what, utable, fails, depth) if not success then return false, result end override_from(result, t, { 'customary', 'default', 'link', 'symbol', 'symlink' }) local multiplier = t.multiplier if multiplier then result.multiplier = tostring(multiplier) result.scale = result.scale * multiplier end return true, result end if t.per then return call_make_per(t) end local combo = t.combination -- nil or a table of unitcodes if combo then local multiple = t.multiple if what == 'no_combination' or (what == 'only_multiple' and not multiple) then return false, { 'cvt_bad_unit', unitcode } end -- Recursively create a combination table containing the -- converter table of each unitcode. local result = { utype = t.utype, multiple = multiple, combination = {} } local cvt = result.combination for i, v in ipairs(combo) do local success, t = lookup(parms, v, multiple and 'no_combination' or 'only_multiple', utable, fails, depth) if not success then return false, t end cvt[i] = t end return true, result end local result = shallow_copy(t) result.unitcode = unitcode if result.prefixes then result.si_name = '' result.si_prefix = '' return true, setmetatable(result, unit_prefixed_mt) end return true, setmetatable(result, unit_mt) end local SIprefixes = text_code.SIprefixes for plen = SIprefixes[1] or 2, 1, -1 do -- Look for an SI prefix; should never occur with an alias. -- Check for longer prefix first ('dam' is decametre). -- SIprefixes[1] = prefix maximum #characters (as seen by mw.ustring.sub). local prefix = usub(unitcode, 1, plen) local si = SIprefixes[prefix] if si then local t = utable[usub(unitcode, plen+1)] if t and t.prefixes then local result = shallow_copy(t) result.unitcode = unitcode result.si_name = parms.opt_sp_us and si.name_us or si.name result.si_prefix = si.prefix or prefix result.scale = t.scale * 10 ^ (si.exponent * t.prefixes) return true, setmetatable(result, unit_prefixed_mt) end end end -- Accept user-defined combinations like "acre+m2+ha" or "acre m2 ha" for output. -- If '+' is used, each unit code can include a space, and any error is fatal. -- If ' ' is used and if each space-separated word is a unit code, it is a combo, -- but errors are not fatal so the unit code can be looked up as an extra unit. local err_is_fatal local combo = collection() if unitcode:find('+', 1, true) then err_is_fatal = true for item in (unitcode .. '+'):gmatch('%s*(.-)%s*%+') do if item ~= '' then combo:add(item) end end elseif unitcode:find('%s') then for item in unitcode:gmatch('%S+') do combo:add(item) end end if combo.n > 1 then local function lookup_combo() if what == 'no_combination' or what == 'only_multiple' then return false, { 'cvt_bad_unit', unitcode } end local result = { combination = {} } local cvt = result.combination for i, v in ipairs(combo) do local success, t = lookup(parms, v, 'only_multiple', utable, fails, depth) if not success then return false, t end if i == 1 then result.utype = t.utype else local mismatch = check_mismatch(result, t) if mismatch then return false, mismatch end end cvt[i] = t end return true, result end local success, result = lookup_combo() if success or err_is_fatal then return success, result end end -- Accept any unit with an engineering notation prefix like "e6cuft" -- (million cubic feet), but not chained prefixes like "e3e6cuft", -- and not if the unit is a combination or multiple, -- and not if the unit has an offset or is a built-in. -- Only en digits are accepted. local exponent, baseunit = unitcode:match('^e(%d+)(.*)') if exponent then local engscale = text_code.eng_scales[exponent] if engscale then local success, result = lookup(parms, baseunit, 'no_combination', utable, fails, depth) if success and not (result.offset or result.builtin or result.engscale) then result.unitcode = unitcode -- 'e6cuft' not 'cuft' result.defkey = unitcode -- key to lookup default exception result.engscale = engscale result.scale = result.scale * 10 ^ tonumber(exponent) return true, result end end end -- Look for x/y; split on right-most slash to get scale correct (x/y/z is x/y per z). local top, bottom = unitcode:match('^(.-)/([^/]+)$') if top and not unitcode:find('e%d') then -- If valid, create an automatic per unit for an "x/y" unit code. -- The unitcode must not include extraneous spaces. -- Engineering notation (apart from at start and which has been stripped before here), -- is not supported so do not make a per unit if find text like 'e3' in unitcode. local success, result = call_make_per({ per = {top, bottom} }) if success then return true, result end end if not parms.opt_ignore_error and not get_range(unitcode) then -- Want the "what links here" list for the extra_module to show only cases -- where an extra unit is used, so do not require it if invoked from {{val}} -- or if looking up a range word which cannot be a unit. if not extra_units then local success, extra = pcall(function () return require(extra_module).extra_units end) if success and type(extra) == 'table' then extra_units = extra end end if extra_units then -- A unit in one data table might refer to a unit in the other table, so -- switch between them, relying on fails or depth to terminate loops. if not fails[unitcode] then fails[unitcode] = true local other = (utable == all_units) and extra_units or all_units local success, result = lookup(parms, unitcode, what, other, fails, depth) if success then return true, result end end end end if to_en_table then -- At fawiki it is common to translate all digits so a unit like "km2" becomes "km۲". local en_code = ustring.gsub(unitcode, '%d', to_en_table) if en_code ~= unitcode then return lookup(parms, en_code, what, utable, fails, depth) end end return false, { 'cvt_unknown', unitcode } end local function valid_number(num) -- Return true if num is a valid number. -- In Scribunto (different from some standard Lua), when expressed as a string, -- overflow or other problems are indicated with text like "inf" or "nan" -- which are regarded as invalid here (each contains "n"). if type(num) == 'number' and tostring(num):find('n', 1, true) == nil then return true end end local function hyphenated(name, parts) -- Return a hyphenated form of given name (for adjectival usage). -- The name may be linked and the target of the link must not be changed. -- Hypothetical examples: -- [[long ton|ton]] → [[long ton|ton]] (no change) -- [[tonne|long ton]] → [[tonne|long-ton]] -- [[metric ton|long ton]] → [[metric ton|long-ton]] -- [[long ton]] → [[long ton|long-ton]] -- Input can also have multiple links in a single name like: -- [[United States customary units|U.S.]] [[US gallon|gallon]] -- [[mile]]s per [[United States customary units|U.S.]] [[quart]] -- [[long ton]]s per [[short ton]] -- Assume that links cannot be nested (never like "[[abc[[def]]ghi]]"). -- This uses a simple and efficient procedure that works for most cases. -- Some units (if used) would require more, and can later think about -- adding a method to handle exceptions. -- The procedure is to replace each space with a hyphen, but -- not a space after ')' [for "(pre-1954&nbsp;US) nautical mile"], and -- not spaces immediately before '(' or in '(...)' [for cases like -- "British thermal unit (ISO)" and "Calorie (International Steam Table)"]. if name:find(' ', 1, true) then if parts then local pos if name:sub(1, 1) == '(' then pos = name:find(')', 1, true) if pos then return name:sub(1, pos+1) .. name:sub(pos+2):gsub(' ', '-') end elseif name:sub(-1) == ')' then pos = name:find('(', 1, true) if pos then return name:sub(1, pos-2):gsub(' ', '-') .. name:sub(pos-1) end end return name:gsub(' ', '-') end parts = collection() for before, item, after in name:gmatch('([^[]*)(%[%[[^[]*%]%])([^[]*)') do if item:find(' ', 1, true) then local prefix local plen = item:find('|', 1, true) if plen then prefix = item:sub(1, plen) item = item:sub(plen + 1, -3) else prefix = item:sub(1, -3) .. '|' item = item:sub(3, -3) end item = prefix .. hyphenated(item, parts) .. ']]' end parts:add(before:gsub(' ', '-') .. item .. after:gsub(' ', '-')) end if parts.n == 0 then -- No link like "[[...]]" was found in the original name. parts:add(hyphenated(name, parts)) end return table.concat(parts) end return name end local function hyphenated_maybe(parms, want_name, sep, id, inout) -- Return s, f where -- s = id, possibly modified -- f = true if hyphenated -- Possible modifications: hyphenate; prepend '-'; append mid text. if id == nil or id == '' then return '' end local mid = (inout == (parms.opt_flip and 'out' or 'in')) and parms.mid or '' if want_name then if parms.opt_adjectival then return '-' .. hyphenated(id) .. mid, true end if parms.opt_add_s and id:sub(-1) ~= 's' then id = id .. 's' -- for nowiki end end return sep .. id .. mid end local function use_minus(text) -- Return text with Unicode minus instead of '-', if present. if text:sub(1, 1) == '-' then return MINUS .. text:sub(2) end return text end local function digit_groups(parms, text, method) -- Return a numbered table of groups of digits (left-to-right, in local language). -- Parameter method is a number or nil: -- 3 for 3-digit grouping (default), or -- 2 for 3-then-2 grouping (only for digits before decimal mark). local len_right local len_left = text:find('.', 1, true) if len_left then len_right = #text - len_left len_left = len_left - 1 else len_left = #text end local twos = method == 2 and len_left > 5 local groups = collection() local run = len_left local n if run < 4 or (run == 4 and parms.opt_comma5) then if parms.opt_gaps then n = run else n = #text end elseif twos then n = run % 2 == 0 and 1 or 2 else n = run % 3 == 0 and 3 or run % 3 end while run > 0 do groups:add(n) run = run - n n = (twos and run > 3) and 2 or 3 end if len_right then if groups.n == 0 then groups:add(0) end if parms.opt_gaps and len_right > 3 then local want4 = not parms.opt_gaps3 -- true gives no gap before trailing single digit local isfirst = true run = len_right while run > 0 do n = (want4 and run == 4) and 4 or (run > 3 and 3 or run) if isfirst then isfirst = false groups[groups.n] = groups[groups.n] + 1 + n else groups:add(n) end run = run - n end else groups[groups.n] = groups[groups.n] + 1 + len_right end end local pos = 1 for i, length in ipairs(groups) do groups[i] = from_en(text:sub(pos, pos + length - 1)) pos = pos + length end return groups end function with_separator(parms, text) -- for forward declaration above -- Input text is a number in en digits with optional '.' decimal mark. -- Return an equivalent, formatted for display: -- with a custom decimal mark instead of '.', if wanted -- with thousand separators inserted, if wanted -- digits in local language -- The given text is like '123' or '123.' or '12345.6789'. -- The text has no sign (caller inserts that later, if necessary). -- When using gaps, they are inserted before and after the decimal mark. -- Separators are inserted only before the decimal mark. -- A trailing dot (as in '123.') is removed because their use appears to -- be accidental, and such a number should be shown as '123' or '123.0'. -- It is useful for convert to suppress the dot so, for example, '4000.' -- is a simple way of indicating that all the digits are significant. if text:sub(-1) == '.' then text = text:sub(1, -2) end if #text < 4 or parms.opt_nocomma or numsep == '' then return from_en(text) end local groups = digit_groups(parms, text, group_method) if parms.opt_gaps then if groups.n <= 1 then return groups[1] or '' end local nowrap = '<span style="white-space: nowrap">' local gap = '<span style="margin-left: 0.25em">' local close = '</span>' return nowrap .. groups[1] .. gap .. table.concat(groups, close .. gap, 2, groups.n) .. close .. close end return table.concat(groups, numsep) end -- An input value like 1.23e12 is displayed using scientific notation (1.23×10¹²). -- That also makes the output use scientific notation, except for small values. -- In addition, very small or very large output values use scientific notation. -- Use format(fmtpower, significand, '10', exponent) where each argument is a string. local fmtpower = '%s<span style="margin:0 .15em 0 .25em">×</span>%s<sup>%s</sup>' local function with_exponent(parms, show, exponent) -- Return wikitext to display the implied value in scientific notation. -- Input uses en digits; output uses digits in local language. return format(fmtpower, with_separator(parms, show), from_en('10'), use_minus(from_en(tostring(exponent)))) end local function make_sigfig(value, sigfig) -- Return show, exponent that are equivalent to the result of -- converting the number 'value' (where value >= 0) to a string, -- rounded to 'sigfig' significant figures. -- The returned items are: -- show: a string of digits; no sign and no dot; -- there is an implied dot before show. -- exponent: a number (an integer) to shift the implied dot. -- Resulting value = tonumber('.' .. show) * 10^exponent. -- Examples: -- make_sigfig(23.456, 3) returns '235', 2 (.235 * 10^2). -- make_sigfig(0.0023456, 3) returns '235', -2 (.235 * 10^-2). -- make_sigfig(0, 3) returns '000', 1 (.000 * 10^1). if sigfig <= 0 then sigfig = 1 elseif sigfig > maxsigfig then sigfig = maxsigfig end if value == 0 then return string.rep('0', sigfig), 1 end local exp, fracpart = math.modf(log10(value)) if fracpart >= 0 then fracpart = fracpart - 1 exp = exp + 1 end local digits = format('%.0f', 10^(fracpart + sigfig)) if #digits > sigfig then -- Overflow (for sigfig=3: like 0.9999 rounding to "1000"; need "100"). digits = digits:sub(1, sigfig) exp = exp + 1 end assert(#digits == sigfig, 'Bug: rounded number has wrong length') return digits, exp end -- Fraction output format. local fracfmt = { { -- Like {{frac}} (fraction slash). '<span class="frac" role="math">{SIGN}<span class="num">{NUM}</span>&frasl;<span class="den">{DEN}</span></span>', -- 1/2 '<span class="frac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="num">{NUM}</span>&frasl;<span class="den">{DEN}</span></span>', -- 1+2/3 style = 'frac', }, { -- Like {{sfrac}} (stacked fraction, that is, horizontal bar). '<span class="sfrac tion" role="math">{SIGN}<span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span>', -- 1//2 '<span class="sfrac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="tion"><span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span></span>', -- 1+2//3 style = 'sfrac', }, } local function format_fraction(parms, inout, negative, wholestr, numstr, denstr, do_spell, style) -- Return wikitext for a fraction, possibly spelled. -- Inputs use en digits and have no sign; output uses digits in local language. local wikitext if not style then style = parms.opt_fraction_horizontal and 2 or 1 end if wholestr == '' then wholestr = nil end local substitute = { SIGN = negative and MINUS or '', WHOLE = wholestr and with_separator(parms, wholestr), NUM = from_en(numstr), DEN = from_en(denstr), } wikitext = fracfmt[style][wholestr and 2 or 1]:gsub('{(%u+)}', substitute) if do_spell then if negative then if wholestr then wholestr = '-' .. wholestr else numstr = '-' .. numstr end end local s = spell_number(parms, inout, wholestr, numstr, denstr) if s then return s end end add_style(parms, fracfmt[style].style) return wikitext end local function format_number(parms, show, exponent, isnegative) -- Parameter show is a string or a table containing strings. -- Each string is a formatted number in en digits and optional '.' decimal mark. -- A table represents a fraction: integer, numerator, denominator; -- if a table is given, exponent must be nil. -- Return t where t is a table with fields: -- show = wikitext formatted to display implied value -- (digits in local language) -- is_scientific = true if show uses scientific notation -- clean = unformatted show (possibly adjusted and with inserted '.') -- (en digits) -- sign = '' or MINUS -- exponent = exponent (possibly adjusted) -- The clean and exponent fields can be used to calculate the -- rounded absolute value, if needed. -- -- The value implied by the arguments is found from: -- exponent is nil; and -- show is a string of digits (no sign), with an optional dot; -- show = '123.4' is value 123.4, '1234' is value 1234.0; -- or: -- exponent is an integer indicating where dot should be; -- show is a string of digits (no sign and no dot); -- there is an implied dot before show; -- show does not start with '0'; -- show = '1234', exponent = 3 is value 0.1234*10^3 = 123.4. -- -- The formatted result: -- * Is for an output value and is spelled if wanted and possible. -- * Includes a Unicode minus if isnegative and not spelled. -- * Uses a custom decimal mark, if wanted. -- * Has digits grouped where necessary, if wanted. -- * Uses scientific notation if requested, or for very small or large values -- (which forces result to not be spelled). -- * Has no more than maxsigfig significant digits -- (same as old template and {{#expr}}). local xhi, xlo -- these control when scientific notation (exponent) is used if parms.opt_scientific then xhi, xlo = 4, 2 -- default for output if input uses e-notation elseif parms.opt_scientific_always then xhi, xlo = 0, 0 -- always use scientific notation (experimental) else xhi, xlo = 10, 4 -- default end local sign = isnegative and MINUS or '' local maxlen = maxsigfig local tfrac if type(show) == 'table' then tfrac = show show = tfrac.wholestr assert(exponent == nil, 'Bug: exponent given with fraction') end if not tfrac and not exponent then local integer, dot, decimals = show:match('^(%d*)(%.?)(.*)') if integer == '0' or integer == '' then local zeros, figs = decimals:match('^(0*)([^0]?.*)') if #figs == 0 then if #zeros > maxlen then show = '0.' .. zeros:sub(1, maxlen) end elseif #zeros >= xlo then show = figs exponent = -#zeros elseif #figs > maxlen then show = '0.' .. zeros .. figs:sub(1, maxlen) end elseif #integer >= xhi then show = integer .. decimals exponent = #integer else maxlen = maxlen + #dot if #show > maxlen then show = show:sub(1, maxlen) end end end if exponent then local function zeros(n) return string.rep('0', n) end if #show > maxlen then show = show:sub(1, maxlen) end if exponent > xhi or exponent <= -xlo or (exponent == xhi and show ~= '1' .. zeros(xhi - 1)) then -- When xhi, xlo = 10, 4 (the default), scientific notation is used if the -- rounded value satisfies: value >= 1e9 or value < 1e-4 (1e9 = 0.1e10), -- except if show is '1000000000' (1e9), for example: -- {{convert|1000000000|m|m|sigfig=10}} → 1,000,000,000 metres (1,000,000,000 m) local significand if #show > 1 then significand = show:sub(1, 1) .. '.' .. show:sub(2) else significand = show end return { clean = '.' .. show, exponent = exponent, sign = sign, show = sign .. with_exponent(parms, significand, exponent-1), is_scientific = true, } end if exponent >= #show then show = show .. zeros(exponent - #show) -- result has no dot elseif exponent <= 0 then show = '0.' .. zeros(-exponent) .. show else show = show:sub(1, exponent) .. '.' .. show:sub(exponent+1) end end local formatted_show if tfrac then show = tostring(tfrac.value) -- to set clean in returned table formatted_show = format_fraction(parms, 'out', isnegative, tfrac.wholestr, tfrac.numstr, tfrac.denstr, parms.opt_spell_out) else if isnegative and show:match('^0.?0*$') then sign = '' -- don't show minus if result is negative but rounds to zero end formatted_show = sign .. with_separator(parms, show) if parms.opt_spell_out then formatted_show = spell_number(parms, 'out', sign .. show) or formatted_show end end return { clean = show, sign = sign, show = formatted_show, is_scientific = false, -- to avoid calling __index } end local function extract_fraction(parms, text, negative) -- If text represents a fraction, return -- value, altvalue, show, denominator -- where -- value is a number (value of the fraction in argument text) -- altvalue is an alternate interpretation of any fraction for the hands -- unit where "12.1+3/4" means 12 hands 1.75 inches -- show is a string (formatted text for display of an input value, -- and is spelled if wanted and possible) -- denominator is value of the denominator in the fraction -- Otherwise, return nil. -- Input uses en digits and '.' decimal mark (input has been translated). -- Output uses digits in local language and local decimal mark, if any. ------------------------------------------------------------------------ -- Originally this function accepted x+y/z where x, y, z were any valid -- numbers, possibly with a sign. For example '1.23e+2+1.2/2.4' = 123.5, -- and '2-3/8' = 1.625. However, such usages were found to be errors or -- misunderstandings, so since August 2014 the following restrictions apply: -- x (if present) is an integer or has a single digit after decimal mark -- y and z are unsigned integers -- e-notation is not accepted -- The overall number can start with '+' or '-' (so '12+3/4' and '+12+3/4' -- and '-12-3/4' are valid). -- Any leading negative sign is removed by the caller, so only inputs -- like the following are accepted here (may have whitespace): -- negative = false false true (there was a leading '-') -- text = '2/3' '+2/3' '2/3' -- text = '1+2/3' '+1+2/3' '1-2/3' -- text = '12.3+1/2' '+12.3+1/2' '12.3-1/2' -- Values like '12.3+1/2' are accepted, but are intended only for use -- with the hands unit (not worth adding code to enforce that). ------------------------------------------------------------------------ local leading_plus, prefix, numstr, slashes, denstr = text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*(/+)%s*(%d+)%s*$') if not leading_plus then -- Accept a single U+2044 fraction slash because that may be pasted. leading_plus, prefix, numstr, denstr = text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*⁄%s*(%d+)%s*$') slashes = '/' end local numerator = tonumber(numstr) local denominator = tonumber(denstr) if numerator == nil or denominator == nil or (negative and leading_plus ~= '') then return nil end local whole, wholestr if prefix == '' then wholestr = '' whole = 0 else -- Any prefix must be like '12+' or '12-' (whole number and fraction sign); -- '12.3+' and '12.3-' are also accepted (single digit after decimal point) -- because '12.3+1/2 hands' is valid (12 hands 3½ inches). local num1, num2, frac_sign = prefix:match('^(%d+)(%.?%d?)%s*([+%-])$') if num1 == nil then return nil end if num2 == '' then -- num2 must be '' or like '.1' but not '.' or '.12' wholestr = num1 else if #num2 ~= 2 then return nil end wholestr = num1 .. num2 end if frac_sign ~= (negative and '-' or '+') then return nil end whole = tonumber(wholestr) if whole == nil then return nil end end local value = whole + numerator / denominator if not valid_number(value) then return nil end local altvalue = whole + numerator / (denominator * 10) local style = #slashes -- kludge: 1 or 2 slashes can be used to select style if style > 2 then style = 2 end local wikitext = format_fraction(parms, 'in', negative, leading_plus .. wholestr, numstr, denstr, parms.opt_spell_in, style) return value, altvalue, wikitext, denominator end local function extract_number(parms, text, another, no_fraction) -- Return true, info if can extract a number from text, -- where info is a table with the result, -- or return false, t where t is an error message table. -- Input can use en digits or digits in local language and can -- have references at the end. Accepting references is intended -- for use in infoboxes with a field for a value passed to convert. -- Parameter another = true if the expected value is not the first. -- Before processing, the input text is cleaned: -- * Any thousand separators (valid or not) are removed. -- * Any sign is replaced with '-' (if negative) or '' (otherwise). -- That replaces Unicode minus with '-'. -- If successful, the returned info table contains named fields: -- value = a valid number -- altvalue = a valid number, usually same as value but different -- if fraction used (for hands unit) -- singular = true if value is 1 or -1 (to use singular form of units) -- clean = cleaned text with any separators and sign removed -- (en digits and '.' decimal mark) -- show = text formatted for output, possibly with ref strip markers -- (digits in local language and custom decimal mark) -- The resulting show: -- * Is for an input value and is spelled if wanted and possible. -- * Has a rounded value, if wanted. -- * Has digits grouped where necessary, if wanted. -- * If negative, a Unicode minus is used; otherwise the sign is -- '+' (if the input text used '+'), or is '' (if no sign in input). text = strip(text or '') local reference local pos = text:find('\127', 1, true) if pos then local before = text:sub(1, pos - 1) local remainder = text:sub(pos) local refs = {} while #remainder > 0 do local ref, spaces ref, spaces, remainder = remainder:match('^(\127[^\127]*UNIQ[^\127]*%-ref[^\127]*\127)(%s*)(.*)') if ref then table.insert(refs, ref) else refs = {} break end end if #refs > 0 then text = strip(before) reference = table.concat(refs) end end local clean = to_en(text, parms) if clean == '' then return false, { another and 'cvt_no_num2' or 'cvt_no_num' } end local isnegative, propersign = false, '' -- most common case local singular, show, denominator local value = tonumber(clean) local altvalue if value then local sign = clean:sub(1, 1) if sign == '+' or sign == '-' then propersign = (sign == '+') and '+' or MINUS clean = clean:sub(2) end if value < 0 then isnegative = true value = -value end else local valstr for _, prefix in ipairs({ '-', MINUS, '&minus;' }) do -- Including '-' sets isnegative in case input is a fraction like '-2-3/4'. local plen = #prefix if clean:sub(1, plen) == prefix then valstr = clean:sub(plen + 1) if valstr:match('^%s') then -- "- 1" is invalid but "-1 - 1/2" is ok return false, { 'cvt_bad_num', text } end break end end if valstr then isnegative = true propersign = MINUS clean = valstr value = tonumber(clean) end if value == nil then if not no_fraction then value, altvalue, show, denominator = extract_fraction(parms, clean, isnegative) end if value == nil then return false, { 'cvt_bad_num', text } end if value <= 1 then singular = true -- for example, "½ mile" or "one half mile" (singular unit) end end end if not valid_number(value) then -- for example, "1e310" may overflow return false, { 'cvt_invalid_num' } end if show == nil then -- clean is a non-empty string with no spaces, and does not represent a fraction, -- and value = tonumber(clean) is a number >= 0. -- If the input uses e-notation, show will be displayed using a power of ten, but -- we use the number as given so it might not be normalized scientific notation. -- The input value is spelled if specified so any e-notation is ignored; -- that allows input like 2e6 to be spelled as "two million" which works -- because the spell module converts '2e6' to '2000000' before spelling. local function rounded(value, default, exponent) local precision = parms.opt_ri if precision then local fmt = '%.' .. format('%d', precision) .. 'f' local result = fmt:format(tonumber(value) + 2e-14) -- fudge for some common cases of bad rounding if not exponent then singular = (tonumber(result) == 1) end return result end return default end singular = (value == 1) local scientific local significand, exponent = clean:match('^([%d.]+)[Ee]([+%-]?%d+)') if significand then show = with_exponent(parms, rounded(significand, significand, exponent), exponent) scientific = true else show = with_separator(parms, rounded(value, clean)) end show = propersign .. show if parms.opt_spell_in then show = spell_number(parms, 'in', propersign .. rounded(value, clean)) or show scientific = false end if scientific then parms.opt_scientific = true end end if isnegative and (value ~= 0) then value = -value altvalue = -(altvalue or value) end return true, { value = value, altvalue = altvalue or value, singular = singular, clean = clean, show = show .. (reference or ''), denominator = denominator, } end local function get_number(text) -- Return v, f where: -- v = nil (text is not a number) -- or -- v = value of text (text is a number) -- f = true if value is an integer -- Input can use en digits or digits in local language or separators, -- but no Unicode minus, and no fraction. if text then local number = tonumber(to_en(text)) if number then local _, fracpart = math.modf(number) return number, (fracpart == 0) end end end local function gcd(a, b) -- Return the greatest common denominator for the given values, -- which are known to be positive integers. if a > b then a, b = b, a end if a <= 0 then return b end local r = b % a if r <= 0 then return a end if r == 1 then return 1 end return gcd(r, a) end local function fraction_table(value, denominator) -- Return value as a string or a table: -- * If result is a string, there is no fraction, and the result -- is value formatted as a string of en digits. -- * If result is a table, it represents a fraction with named fields: -- wholestr, numstr, denstr (strings of en digits for integer, numerator, denominator). -- The result is rounded to the nearest multiple of (1/denominator). -- If the multiple is zero, no fraction is included. -- No fraction is included if value is very large as the fraction would -- be unhelpful, particularly if scientific notation is required. -- Input value is a non-negative number. -- Input denominator is a positive integer for the desired fraction. if value <= 0 then return '0' end if denominator <= 0 or value > 1e8 then return format('%.2f', value) end local integer, decimals = math.modf(value) local numerator = floor((decimals * denominator) + 0.5 + 2e-14) -- add fudge for some common cases of bad rounding if numerator >= denominator then integer = integer + 1 numerator = 0 end local wholestr = tostring(integer) if numerator > 0 then local div = gcd(numerator, denominator) if div > 1 then numerator = numerator / div denominator = denominator / div end return { wholestr = (integer > 0) and wholestr or '', numstr = tostring(numerator), denstr = tostring(denominator), value = value, } end return wholestr end local function preunits(count, preunit1, preunit2) -- If count is 1: -- ignore preunit2 -- return p1 -- else: -- preunit1 is used for preunit2 if the latter is empty -- return p1, p2 -- where: -- p1 is text to insert before the input unit -- p2 is text to insert before the output unit -- p1 or p2 may be nil to mean "no preunit" -- Using '+' gives output like "5+ feet" (no space before, but space after). local function withspace(text, wantboth) -- Return text with space before and, if wantboth, after. -- However, no space is added if there is a space or '&nbsp;' or '-' -- at that position ('-' is for adjectival text). -- There is also no space if text starts with '&' -- (e.g. '&deg;' would display a degree symbol with no preceding space). local char = text:sub(1, 1) if char == '&' then return text -- an html entity can be used to specify the exact display end if not (char == ' ' or char == '-' or char == '+') then text = ' ' .. text end if wantboth then char = text:sub(-1, -1) if not (char == ' ' or char == '-' or text:sub(-6, -1) == '&nbsp;') then text = text .. ' ' end end return text end local PLUS = '+ ' preunit1 = preunit1 or '' local trim1 = strip(preunit1) if count == 1 then if trim1 == '' then return nil end if trim1 == '+' then return PLUS end return withspace(preunit1, true) end preunit1 = withspace(preunit1) preunit2 = preunit2 or '' local trim2 = strip(preunit2) if trim1 == '+' then if trim2 == '' or trim2 == '+' then return PLUS, PLUS end preunit1 = PLUS end if trim2 == '' then if trim1 == '' then return nil, nil end preunit2 = preunit1 elseif trim2 == '+' then preunit2 = PLUS elseif trim2 == '&#32;' then -- trick to make preunit2 empty preunit2 = nil else preunit2 = withspace(preunit2) end return preunit1, preunit2 end local function range_text(range, want_name, parms, before, after, inout, options) -- Return before .. rtext .. after -- where rtext is the text that separates two values in a range. local rtext, adj_text, exception options = options or {} if type(range) == 'table' then -- Table must specify range text for ('off' and 'on') or ('input' and 'output'), -- and may specify range text for 'adj=on', -- and may specify exception = true. rtext = range[want_name and 'off' or 'on'] or range[((inout == 'in') == (parms.opt_flip == true)) and 'output' or 'input'] adj_text = range['adj'] exception = range['exception'] else rtext = range end if parms.opt_adjectival then if want_name or (exception and parms.abbr_org == 'on') then rtext = adj_text or rtext:gsub(' ', '-'):gsub('&nbsp;', '-') end end if rtext == '–' and (options.spaced or after:sub(1, #MINUS) == MINUS) then rtext = '&nbsp;– ' end return before .. rtext .. after end local function get_composite(parms, iparm, in_unit_table) -- Look for a composite input unit. For example, {{convert|1|yd|2|ft|3|in}} -- would result in a call to this function with -- iparm = 3 (parms[iparm] = "2", just after the first unit) -- in_unit_table = (unit table for "yd"; contains value 1 for number of yards) -- Return true, iparm, unit where -- iparm = index just after the composite units (7 in above example) -- unit = composite unit table holding all input units, -- or return true if no composite unit is present in parms, -- or return false, t where t is an error message table. local default, subinfo local composite_units, count = { in_unit_table }, 1 local fixups = {} local total = in_unit_table.valinfo[1].value local subunit = in_unit_table while subunit.subdivs do -- subdivs is nil or a table of allowed subdivisions local subcode = strip(parms[iparm+1]) local subdiv = subunit.subdivs[subcode] or subunit.subdivs[(all_units[subcode] or {}).target] if not subdiv then break end local success success, subunit = lookup(parms, subcode, 'no_combination') if not success then return false, subunit end -- should never occur success, subinfo = extract_number(parms, parms[iparm]) if not success then return false, subinfo end iparm = iparm + 2 subunit.inout = 'in' subunit.valinfo = { subinfo } -- Recalculate total as a number of subdivisions. -- subdiv[1] = number of subdivisions per previous unit (integer > 1). total = total * subdiv[1] + subinfo.value if not default then -- set by the first subdiv with a default defined default = subdiv.default end count = count + 1 composite_units[count] = subunit if subdiv.unit or subdiv.name then fixups[count] = { unit = subdiv.unit, name = subdiv.name, valinfo = subunit.valinfo } end end if count == 1 then return true -- no error and no composite unit end for i, fixup in pairs(fixups) do local unit = fixup.unit local name = fixup.name if not unit or (count > 2 and name) then composite_units[i].fixed_name = name else local success, alternate = lookup(parms, unit, 'no_combination') if not success then return false, alternate end -- should never occur alternate.inout = 'in' alternate.valinfo = fixup.valinfo composite_units[i] = alternate end end return true, iparm, { utype = in_unit_table.utype, scale = subunit.scale, -- scale of last (least significant) unit valinfo = { { value = total, clean = subinfo.clean, denominator = subinfo.denominator } }, composite = composite_units, default = default or in_unit_table.default } end local function translate_parms(parms, kv_pairs) -- Update fields in parms by translating each key:value in kv_pairs to terms -- used by this module (may involve translating from local language to English). -- Also, checks are performed which may display warnings, if enabled. -- Return true if successful or return false, t where t is an error message table. currency_text = nil -- local testing can hold module in memory; must clear globals if kv_pairs.adj and kv_pairs.sing then -- For enwiki (before translation), warn if attempt to use adj and sing -- as the latter is a deprecated alias for the former. if kv_pairs.adj ~= kv_pairs.sing and kv_pairs.sing ~= '' then add_warning(parms, 1, 'cvt_unknown_option', 'sing=' .. kv_pairs.sing) end kv_pairs.sing = nil end kv_pairs.comma = kv_pairs.comma or config.comma -- for plwiki who want default comma=5 for loc_name, loc_value in pairs(kv_pairs) do local en_name = text_code.en_option_name[loc_name] if en_name then local en_value = text_code.en_option_value[en_name] if en_value == 'INTEGER' then -- altitude_ft, altitude_m, frac, sigfig en_value = nil if loc_value == '' then add_warning(parms, 2, 'cvt_empty_option', loc_name) else local minimum local number, is_integer = get_number(loc_value) if en_name == 'sigfig' then minimum = 1 elseif en_name == 'frac' then minimum = 2 if number and number < 0 then parms.opt_fraction_horizontal = true number = -number end else minimum = -1e6 end if number and is_integer and number >= minimum then en_value = number else local m if en_name == 'frac' then m = 'cvt_bad_frac' elseif en_name == 'sigfig' then m = 'cvt_bad_sigfig' else m = 'cvt_bad_altitude' end add_warning(parms, 1, m, loc_name .. '=' .. loc_value) end end elseif en_value == 'TEXT' then -- $, input, qid, qual, stylein, styleout, tracking en_value = loc_value ~= '' and loc_value or nil -- accept non-empty user text with no validation if not en_value and (en_name == '$' or en_name == 'qid' or en_name == 'qual') then add_warning(parms, 2, 'cvt_empty_option', loc_name) elseif en_name == '$' then -- Value should be a single character like "€" for the euro currency symbol, but anything is accepted. currency_text = (loc_value == 'euro') and '€' or loc_value elseif en_name == 'input' then -- May have something like {{convert|input=}} (empty input) if source is an infobox -- with optional fields. In that case, want to output nothing rather than an error. parms.input_text = loc_value -- keep input because parms.input is nil if loc_value == '' end else en_value = en_value[loc_value] if en_value and en_value:sub(-1) == '?' then en_value = en_value:sub(1, -2) add_warning(parms, -1, 'cvt_deprecated', loc_name .. '=' .. loc_value) end if en_value == nil then if loc_value == '' then add_warning(parms, 2, 'cvt_empty_option', loc_name) else add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value) end elseif en_value == '' then en_value = nil -- an ignored option like adj=off elseif type(en_value) == 'string' and en_value:sub(1, 4) == 'opt_' then for _, v in ipairs(split(en_value, ',')) do local lhs, rhs = v:match('^(.-)=(.+)$') if rhs then parms[lhs] = tonumber(rhs) or rhs else parms[v] = true end end en_value = nil end end parms[en_name] = en_value else add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value) end end local abbr_entered = parms.abbr local cfg_abbr = config.abbr if cfg_abbr then -- Don't warn if invalid because every convert would show that warning. if cfg_abbr == 'on always' then parms.abbr = 'on' elseif cfg_abbr == 'off always' then parms.abbr = 'off' elseif parms.abbr == nil then if cfg_abbr == 'on default' then parms.abbr = 'on' elseif cfg_abbr == 'off default' then parms.abbr = 'off' end end end if parms.abbr then if parms.abbr == 'unit' then parms.abbr = 'on' parms.number_word = true end parms.abbr_org = parms.abbr -- original abbr, before any flip elseif parms.opt_hand_hh then parms.abbr_org = 'on' parms.abbr = 'on' else parms.abbr = 'out' -- default is to abbreviate output only (use symbol, not name) end if parms.opt_order_out then -- Disable options that do not work in a useful way with order=out. parms.opt_flip = nil -- override adj=flip parms.opt_spell_in = nil parms.opt_spell_out = nil parms.opt_spell_upper = nil end if parms.opt_spell_out and not abbr_entered then parms.abbr = 'off' -- should show unit name when spelling the output value end if parms.opt_flip then local function swap_in_out(option) local value = parms[option] if value == 'in' then parms[option] = 'out' elseif value == 'out' then parms[option] = 'in' end end swap_in_out('abbr') swap_in_out('lk') if parms.opt_spell_in and not parms.opt_spell_out then -- For simplicity, and because it does not appear to be needed, -- user cannot set an option to spell the output only. parms.opt_spell_in = nil parms.opt_spell_out = true end end if parms.opt_spell_upper then parms.spell_upper = parms.opt_flip and 'out' or 'in' end if parms.opt_table or parms.opt_tablecen then if abbr_entered == nil and parms.lk == nil then parms.opt_values = true end parms.table_align = parms.opt_table and 'right' or 'center' end if parms.table_align or parms.opt_sortable_on then parms.need_table_or_sort = true end local disp_joins = text_code.disp_joins local default_joins = disp_joins['b'] parms.join_between = default_joins[3] or '; ' local disp = parms.disp if disp == nil then -- special case for the most common setting parms.joins = default_joins elseif disp == 'x' then -- Later, parms.joins is set from the input parameters. else -- Old template does this. local abbr = parms.abbr if disp == 'slash' then if abbr_entered == nil then disp = 'slash-nbsp' elseif abbr == 'in' or abbr == 'out' then disp = 'slash-sp' else disp = 'slash-nosp' end elseif disp == 'sqbr' then if abbr == 'on' then disp = 'sqbr-nbsp' else disp = 'sqbr-sp' end end parms.joins = disp_joins[disp] or default_joins parms.join_between = parms.joins[3] or parms.join_between parms.wantname = parms.joins.wantname end if (en_default and not parms.opt_lang_local and (parms[1] or ''):find('%d')) or parms.opt_lang_en then from_en_table = nil end if en_default and from_en_table then -- For hiwiki: localized symbol/name is defined with the US symbol/name field, -- and is used if output uses localized numbers. parms.opt_sp_us = true end return true end local function get_values(parms) -- If successful, update parms and return true, v, i where -- v = table of input values -- i = index to next entry in parms after those processed here -- or return false, t where t is an error message table. local valinfo = collection() -- numbered table of input values local range = collection() -- numbered table of range items (having, for example, 2 range items requires 3 input values) local had_nocomma -- true if removed "nocomma" kludge from second parameter (like "tonocomma") local parm2 = strip(parms[2]) if parm2 and parm2:sub(-7, -1) == 'nocomma' then parms[2] = strip(parm2:sub(1, -8)) parms.opt_nocomma = true had_nocomma = true end local function extractor(i) -- If the parameter is not a value, try unpacking it as a range ("1-23" for "1 to 23"). -- However, "-1-2/3" is a negative fraction (-1⅔), so it must be extracted first. -- Do not unpack a parameter if it is like "3-1/2" which is sometimes incorrectly -- used instead of "3+1/2" (and which should not be interpreted as "3 to ½"). -- Unpacked items are inserted into the parms table. -- The tail recursion allows combinations like "1x2 to 3x4". local valstr = strip(parms[i]) -- trim so any '-' as a negative sign will be at start local success, result = extract_number(parms, valstr, i > 1) if not success and valstr and i < 20 then -- check i to limit abuse local lhs, sep, rhs = valstr:match('^(%S+)%s+(%S+)%s+(%S.*)') if lhs and not (sep == '-' and rhs:match('/')) then if sep:find('%d') then return success, result -- to reject {{convert|1 234 567|m}} with a decent message (en only) end parms[i] = rhs table.insert(parms, i, sep) table.insert(parms, i, lhs) return extractor(i) end if not valstr:match('%-.*/') then for _, sep in ipairs(text_code.ranges.words) do local start, stop = valstr:find(sep, 2, true) -- start at 2 to skip any negative sign for range '-' if start then parms[i] = valstr:sub(stop + 1) table.insert(parms, i, sep) table.insert(parms, i, valstr:sub(1, start - 1)) return extractor(i) end end end end return success, result end local i = 1 local is_change while true do local success, info = extractor(i) -- need to set parms.opt_nocomma before calling this if not success then return false, info end i = i + 1 if is_change then info.is_change = true -- value is after "±" and so is a change (significant for range like {{convert|5|±|5|°C}}) is_change = nil end valinfo:add(info) local range_item = get_range(strip(parms[i])) if not range_item then break end i = i + 1 range:add(range_item) if type(range_item) == 'table' then -- For range "x", if append unit to some values, append it to all. parms.in_range_x = parms.in_range_x or range_item.in_range_x parms.out_range_x = parms.out_range_x or range_item.out_range_x parms.abbr_range_x = parms.abbr_range_x or range_item.abbr_range_x is_change = range_item.is_range_change end end if range.n > 0 then if range.n > 30 then -- limit abuse, although 4 is a more likely upper limit return false, { 'cvt_invalid_num' } -- misleading message but it will do end parms.range = range elseif had_nocomma then return false, { 'cvt_unknown', parm2 } end return true, valinfo, i end local function simple_get_values(parms) -- If input is like "{{convert|valid_value|valid_unit|...}}", -- return true, i, in_unit, in_unit_table -- i = index in parms of what follows valid_unit, if anything. -- The valid_value is not negative and does not use a fraction, and -- no options requiring further processing of the input are used. -- Otherwise, return nothing or return false, parm1 for caller to interpret. -- Testing shows this function is successful for 96% of converts in articles, -- and that on average it speeds up converts by 8%. local clean = to_en(strip(parms[1] or ''), parms) if parms.opt_ri or parms.opt_spell_in or #clean > 10 or not clean:match('^[0-9.]+$') then return false, clean end local value = tonumber(clean) if not value then return end local info = { value = value, altvalue = value, singular = (value == 1), clean = clean, show = with_separator(parms, clean), } local in_unit = strip(parms[2]) local success, in_unit_table = lookup(parms, in_unit, 'no_combination') if not success then return end in_unit_table.valinfo = { info } return true, 3, in_unit, in_unit_table end local function wikidata_call(parms, operation, ...) -- Return true, s where s is the result of a Wikidata operation, -- or return false, t where t is an error message table. local function worker(...) wikidata_code = wikidata_code or require(wikidata_module) wikidata_data = wikidata_data or mw.loadData(wikidata_data_module) return wikidata_code[operation](wikidata_data, ...) end local success, status, result = pcall(worker, ...) if success then return status, result end if parms.opt_sortable_debug then -- Use debug=yes to crash if an error while accessing Wikidata. error('Error accessing Wikidata: ' .. status, 0) end return false, { 'cvt_wd_fail' } end local function get_parms(parms, args) -- If successful, update parms and return true, unit where -- parms is a table of all arguments passed to the template -- converted to named arguments, and -- unit is the input unit table; -- or return false, t where t is an error message table. -- For special processing (not a convert), can also return -- true, wikitext where wikitext is the final result. -- The returned input unit table may be for a fake unit using the specified -- unit code as the symbol and name, and with bad_mcode = message code table. -- MediaWiki removes leading and trailing whitespace from the values of -- named arguments. However, the values of numbered arguments include any -- whitespace entered in the template, and whitespace is used by some -- parameters (example: the numbered parameters associated with "disp=x"). local kv_pairs = {} -- table of input key:value pairs where key is a name; needed because cannot iterate parms and add new fields to it for k, v in pairs(args) do if type(k) == 'number' or k == 'test' then -- parameter "test" is reserved for testing and is not translated parms[k] = v else kv_pairs[k] = v end end if parms.test == 'wikidata' then local ulookup = function (ucode) -- Use empty table for parms so it does not accumulate results when used repeatedly. return lookup({}, ucode, 'no_combination') end return wikidata_call(parms, '_listunits', ulookup) end local success, msg = translate_parms(parms, kv_pairs) if not success then return false, msg end if parms.input then success, msg = wikidata_call(parms, '_adjustparameters', parms, 1) if not success then return false, msg end end local success, i, in_unit, in_unit_table = simple_get_values(parms) if not success then if type(i) == 'string' and i:match('^NNN+$') then -- Some infoboxes have examples like {{convert|NNN|m}} (3 or more "N"). -- Output an empty string for these. return false, { 'cvt_no_output' } end local valinfo success, valinfo, i = get_values(parms) if not success then return false, valinfo end in_unit = strip(parms[i]) i = i + 1 success, in_unit_table = lookup(parms, in_unit, 'no_combination') if not success then in_unit = in_unit or '' if parms.opt_ignore_error then -- display given unit code with no error (for use with {{val}}) in_unit_table = '' -- suppress error message and prevent processing of output unit end in_unit_table = setmetatable({ symbol = in_unit, name2 = in_unit, utype = in_unit, scale = 1, default = '', defkey = '', linkey = '', bad_mcode = in_unit_table }, unit_mt) end in_unit_table.valinfo = valinfo end if parms.test == 'msg' then -- Am testing the messages produced when no output unit is specified, and -- the input unit has a missing or invalid default. -- Set two units for testing that. -- LATER: Remove this code. if in_unit == 'chain' then in_unit_table.default = nil -- no default elseif in_unit == 'rd' then in_unit_table.default = "ft!X!m" -- an invalid expression end end in_unit_table.inout = 'in' -- this is an input unit if not parms.range then local success, inext, composite_unit = get_composite(parms, i, in_unit_table) if not success then return false, inext end if composite_unit then in_unit_table = composite_unit i = inext end end if in_unit_table.builtin == 'mach' then -- As with old template, a number following Mach as the input unit is the altitude. -- That is deprecated: should use altitude_ft=NUMBER or altitude_m=NUMBER. local success, info success = tonumber(parms[i]) -- this will often work and will give correct result for values like 2e4 without forcing output scientific notation if success then info = { value = success } else success, info = extract_number(parms, parms[i], false, true) end if success then i = i + 1 in_unit_table.altitude = info.value end end local word = strip(parms[i]) i = i + 1 local precision, is_bad_precision local function set_precision(text) local number, is_integer = get_number(text) if number then if is_integer then precision = number else precision = text is_bad_precision = true end return true -- text was used for precision, good or bad end end if word and not set_precision(word) then parms.out_unit = parms.out_unit or word if set_precision(strip(parms[i])) then i = i + 1 end end if parms.opt_adj_mid then word = parms[i] i = i + 1 if word then -- mid-text words if word:sub(1, 1) == '-' then parms.mid = word else parms.mid = ' ' .. word end end end if parms.opt_one_preunit then parms[parms.opt_flip and 'preunit2' or 'preunit1'] = preunits(1, parms[i]) i = i + 1 end if parms.disp == 'x' then -- Following is reasonably compatible with the old template. local first = parms[i] or '' local second = parms[i+1] or '' i = i + 2 if strip(first) == '' then -- user can enter '&#32;' rather than ' ' to avoid the default first = ' [&nbsp;' .. first second = '&nbsp;]' .. second end parms.joins = { first, second } elseif parms.opt_two_preunits then local p1, p2 = preunits(2, parms[i], parms[i+1]) i = i + 2 if parms.preunit1 then -- To simplify documentation, allow unlikely use of adj=pre with disp=preunit -- (however, an output unit must be specified with adj=pre and with disp=preunit). parms.preunit1 = parms.preunit1 .. p1 parms.preunit2 = p2 else parms.preunit1, parms.preunit2 = p1, p2 end end if precision == nil then if set_precision(strip(parms[i])) then i = i + 1 end end if is_bad_precision then add_warning(parms, 1, 'cvt_bad_prec', precision) else parms.precision = precision end for j = i, i + 3 do local parm = parms[j] -- warn if find a non-empty extraneous parameter if parm and parm:match('%S') then add_warning(parms, 1, 'cvt_unknown_option', parm) break end end return true, in_unit_table end local function record_default_precision(parms, out_current, precision) -- If necessary, adjust parameters and return a possibly adjusted precision. -- When converting a range of values where a default precision is required, -- that default is calculated for each value because the result sometimes -- depends on the precise input and output values. This function may cause -- the entire convert process to be repeated in order to ensure that the -- same default precision is used for each individual convert. -- If that were not done, a range like 1000 to 1000.4 may give poor results -- because the first output could be heavily rounded, while the second is not. -- For range 1000.4 to 1000, this function can give the second convert the -- same default precision that was used for the first. if not parms.opt_round_each then local maxdef = out_current.max_default_precision if maxdef then if maxdef < precision then parms.do_convert_again = true out_current.max_default_precision = precision else precision = out_current.max_default_precision end else out_current.max_default_precision = precision end end return precision end local function default_precision(parms, invalue, inclean, denominator, outvalue, in_current, out_current, extra) -- Return a default value for precision (an integer like 2, 0, -2). -- If denominator is not nil, it is the value of the denominator in inclean. -- Code follows procedures used in old template. local fudge = 1e-14 -- {{Order of magnitude}} adds this, so we do too local prec, minprec, adjust local subunit_ignore_trailing_zero local subunit_more_precision -- kludge for "in" used in input like "|2|ft|6|in" local composite = in_current.composite if composite then subunit_ignore_trailing_zero = true -- input "|2|st|10|lb" has precision 0, not -1 if composite[#composite].exception == 'subunit_more_precision' then subunit_more_precision = true -- do not use standard precision with input like "|2|ft|6|in" end end if denominator and denominator > 0 then prec = math.max(log10(denominator), 1) else -- Count digits after decimal mark, handling cases like '12.345e6'. local exponent local integer, dot, decimals, expstr = inclean:match('^(%d*)(%.?)(%d*)(.*)') local e = expstr:sub(1, 1) if e == 'e' or e == 'E' then exponent = tonumber(expstr:sub(2)) end if dot == '' then prec = subunit_ignore_trailing_zero and 0 or -integer:match('0*$'):len() else prec = #decimals end if exponent then -- So '1230' and '1.23e3' both give prec = -1, and '0.00123' and '1.23e-3' give 5. prec = prec - exponent end end if in_current.istemperature and out_current.istemperature then -- Converting between common temperatures (°C, °F, °R, K); not keVT. -- Kelvin value can be almost zero, or small but negative due to precision problems. -- Also, an input value like -300 C (below absolute zero) gives negative kelvins. -- Calculate minimum precision from absolute value. adjust = 0 local kelvin = abs((invalue - in_current.offset) * in_current.scale) if kelvin < 1e-8 then -- assume nonzero due to input or calculation precision problem minprec = 2 else minprec = 2 - floor(log10(kelvin) + fudge) -- 3 sigfigs in kelvin end else if invalue == 0 or outvalue <= 0 then -- We are never called with a negative outvalue, but it might be zero. -- This is special-cased to avoid calculation exceptions. return record_default_precision(parms, out_current, 0) end if out_current.exception == 'integer_more_precision' and floor(invalue) == invalue then -- With certain output units that sometimes give poor results -- with default rounding, use more precision when the input -- value is equal to an integer. An example of a poor result -- is when input 50 gives a smaller output than input 49.5. -- Experiment shows this helps, but it does not eliminate all -- surprises because it is not clear whether "50" should be -- interpreted as "from 45 to 55" or "from 49.5 to 50.5". adjust = -log10(in_current.scale) elseif subunit_more_precision then -- Conversion like "{{convert|6|ft|1|in|cm}}" (where subunit is "in") -- has a non-standard adjust value, to give more output precision. adjust = log10(out_current.scale) + 2 else adjust = log10(abs(invalue / outvalue)) end adjust = adjust + log10(2) -- Ensure that the output has at least two significant figures. minprec = 1 - floor(log10(outvalue) + fudge) end if extra then adjust = extra.adjust or adjust minprec = extra.minprec or minprec end return record_default_precision(parms, out_current, math.max(floor(prec + adjust), minprec)) end local function convert(parms, invalue, info, in_current, out_current) -- Convert given input value from one unit to another. -- Return output_value (a number) if a simple convert, or -- return f, t where -- f = true, t = table of information with results, or -- f = false, t = error message table. local inscale = in_current.scale local outscale = out_current.scale if not in_current.iscomplex and not out_current.iscomplex then return invalue * (inscale / outscale) -- minimize overhead for most common case end if in_current.invert or out_current.invert then -- Inverted units, such as inverse length, inverse time, or -- fuel efficiency. Built-in units do not have invert set. if (in_current.invert or 1) * (out_current.invert or 1) < 0 then return 1 / (invalue * inscale * outscale) end return invalue * (inscale / outscale) elseif in_current.offset then -- Temperature (there are no built-ins for this type of unit). if info.is_change then return invalue * (inscale / outscale) end return (invalue - in_current.offset) * (inscale / outscale) + out_current.offset else -- Built-in unit. local in_builtin = in_current.builtin local out_builtin = out_current.builtin if in_builtin and out_builtin then if in_builtin == out_builtin then return invalue end -- There are no cases (yet) where need to convert from one -- built-in unit to another, so this should never occur. return false, { 'cvt_bug_convert' } end if in_builtin == 'mach' or out_builtin == 'mach' then -- Should check that only one altitude is given but am planning to remove -- in_current.altitude (which can only occur when Mach is the input unit), -- and out_current.altitude cannot occur. local alt = parms.altitude_ft or in_current.altitude if not alt and parms.altitude_m then alt = parms.altitude_m / 0.3048 -- 1 ft = 0.3048 m end local spd = speed_of_sound(alt) if in_builtin == 'mach' then inscale = spd return invalue * (inscale / outscale) end outscale = spd local adjust = 0.1 / inscale return true, { outvalue = invalue * (inscale / outscale), adjust = log10(adjust) + log10(2), } elseif in_builtin == 'hand' then -- 1 hand = 4 inches; 1.2 hands = 6 inches. -- Decimals of a hand are only defined for the first digit, and -- the first fractional digit should be a number of inches (1, 2 or 3). -- However, this code interprets the entire fractional part as the number -- of inches / 10 (so 1.75 inches would be 0.175 hands). -- A value like 12.3 hands is exactly 12*4 + 3 inches; base default precision on that. local integer, fracpart = math.modf(invalue) local inch_value = 4 * integer + 10 * fracpart -- equivalent number of inches local factor = inscale / outscale if factor == 4 then -- Am converting to inches: show exact result, and use "inches" not "in" by default. if parms.abbr_org == nil then out_current.usename = true end local show = format('%g', abs(inch_value)) -- show and clean are unsigned if not show:find('e', 1, true) then return true, { invalue = inch_value, outvalue = inch_value, clean = show, show = show, } end end local outvalue = (integer + 2.5 * fracpart) * factor local fracstr = info.clean:match('%.(.*)') or '' local fmt if fracstr == '' then fmt = '%.0f' else fmt = '%.' .. format('%d', #fracstr - 1) .. 'f' end return true, { invalue = inch_value, clean = format(fmt, inch_value), outvalue = outvalue, minprec = 0, } end end return false, { 'cvt_bug_convert' } -- should never occur end local function user_style(parms, i) -- Return text for a user-specified style for a table cell, or '' if none, -- given i = 1 (input style) or 2 (output style). local style = parms[(i == 1) and 'stylein' or 'styleout'] if style then style = style:gsub('"', '') if style ~= '' then if style:sub(-1) ~= ';' then style = style .. ';' end return style end end return '' end local function make_table_or_sort(parms, invalue, info, in_current, scaled_top) -- Set options to handle output for a table or a sort key, or both. -- The text sort key is based on the value resulting from converting -- the input to a fake base unit with scale = 1, and other properties -- required for a conversion derived from the input unit. -- For other modules, return the sort key in a hidden span element, and -- the scaled value used to generate the sort key. -- If scaled_top is set, it is the scaled value of the numerator of a per unit -- to be combined with this unit (the denominator) to make the sort key. -- Scaling only works with units that convert with a factor (not temperature). local sortkey, scaled_value if parms.opt_sortable_on then local base = { -- a fake unit with enough fields for a valid convert scale = 1, invert = in_current.invert and 1, iscomplex = in_current.iscomplex, offset = in_current.offset and 0, } local outvalue, extra = convert(parms, invalue, info, in_current, base) if extra then outvalue = extra.outvalue end if in_current.istemperature then -- Have converted to kelvin; assume numbers close to zero have a -- rounding error and should be zero. if abs(outvalue) < 1e-12 then outvalue = 0 end end if scaled_top and outvalue ~= 0 then outvalue = scaled_top / outvalue end scaled_value = outvalue if not valid_number(outvalue) then if outvalue < 0 then sortkey = '1000000000000000000' else sortkey = '9000000000000000000' end elseif outvalue == 0 then sortkey = '5000000000000000000' else local mag = floor(log10(abs(outvalue)) + 1e-14) local prefix if outvalue > 0 then prefix = 7000 + mag else prefix = 2999 - mag outvalue = outvalue + 10^(mag+1) end sortkey = format('%d', prefix) .. format('%015.0f', floor(outvalue * 10^(14-mag))) end end local sortspan if sortkey and not parms.table_align then sortspan = parms.opt_sortable_debug and '<span data-sort-value="' .. sortkey .. '♠"><span style="border:1px solid">' .. sortkey .. '♠</span></span>' or '<span data-sort-value="' .. sortkey .. '♠"></span>' parms.join_before = sortspan end if parms.table_align then local sort if sortkey then sort = ' data-sort-value="' .. sortkey .. '"' if parms.opt_sortable_debug then parms.join_before = '<span style="border:1px solid">' .. sortkey .. '</span>' end else sort = '' end local style = 'style="text-align:' .. parms.table_align .. ';' local joins = {} for i = 1, 2 do joins[i] = (i == 1 and '' or '\n|') .. style .. user_style(parms, i) .. '"' .. sort .. '|' end parms.table_joins = joins end return sortspan, scaled_value end local cvt_to_hand local function cvtround(parms, info, in_current, out_current) -- Return true, t where t is a table with the conversion results; fields: -- show = rounded, formatted string with the result of converting value in info, -- using the rounding specified in parms. -- singular = true if result (after rounding and ignoring any negative sign) -- is "1", or like "1.00", or is a fraction with value < 1; -- (and more fields shown below, and a calculated 'absvalue' field). -- or return false, t where t is an error message table. -- Input info.clean uses en digits (it has been translated, if necessary). -- Output show uses en or non-en digits as appropriate, or can be spelled. if out_current.builtin == 'hand' then return cvt_to_hand(parms, info, in_current, out_current) end local invalue = in_current.builtin == 'hand' and info.altvalue or info.value local outvalue, extra = convert(parms, invalue, info, in_current, out_current) if parms.need_table_or_sort then parms.need_table_or_sort = nil -- process using first input value only make_table_or_sort(parms, invalue, info, in_current) end if extra then if not outvalue then return false, extra end invalue = extra.invalue or invalue outvalue = extra.outvalue end if not valid_number(outvalue) then return false, { 'cvt_invalid_num' } end local isnegative if outvalue < 0 then isnegative = true outvalue = -outvalue end local precision, show, exponent local denominator = out_current.frac if denominator then show = fraction_table(outvalue, denominator) else precision = parms.precision if not precision then if parms.sigfig then show, exponent = make_sigfig(outvalue, parms.sigfig) elseif parms.opt_round then local n = parms.opt_round if n == 0.5 then local integer, fracpart = math.modf(floor(2 * outvalue + 0.5) / 2) if fracpart == 0 then show = format('%.0f', integer) else show = format('%.1f', integer + fracpart) end else show = format('%.0f', floor((outvalue / n) + 0.5) * n) end elseif in_current.builtin == 'mach' then local sigfig = info.clean:gsub('^[0.]+', ''):gsub('%.', ''):len() + 1 show, exponent = make_sigfig(outvalue, sigfig) else local inclean = info.clean if extra then inclean = extra.clean or inclean show = extra.show end if not show then precision = default_precision(parms, invalue, inclean, info.denominator, outvalue, in_current, out_current, extra) end end end end if precision then if precision >= 0 then local fudge if precision <= 8 then -- Add a fudge to handle common cases of bad rounding due to inability -- to precisely represent some values. This makes the following work: -- {{convert|-100.1|C|K}} and {{convert|5555000|um|m|2}}. -- Old template uses #expr round, which invokes PHP round(). -- LATER: Investigate how PHP round() works. fudge = 2e-14 else fudge = 0 end local fmt = '%.' .. format('%d', precision) .. 'f' local success success, show = pcall(format, fmt, outvalue + fudge) if not success then return false, { 'cvt_big_prec', tostring(precision) } end else precision = -precision -- #digits to zero (in addition to any digits after dot) local shift = 10 ^ precision show = format('%.0f', outvalue/shift) if show ~= '0' then exponent = #show + precision end end end local t = format_number(parms, show, exponent, isnegative) if type(show) == 'string' then -- Set singular using match because on some systems 0.99999999999999999 is 1.0. if exponent then t.singular = (exponent == 1 and show:match('^10*$')) else t.singular = (show == '1' or show:match('^1%.0*$')) end else t.fraction_table = show t.singular = (outvalue <= 1) -- cannot have 'fraction == 1', but if it were possible it would be singular end t.raw_absvalue = outvalue -- absolute value before rounding return true, setmetatable(t, { __index = function (self, key) if key == 'absvalue' then -- Calculate absolute value after rounding, if needed. local clean, exponent = rawget(self, 'clean'), rawget(self, 'exponent') local value = tonumber(clean) -- absolute value (any negative sign has been ignored) if exponent then value = value * 10^exponent end rawset(self, key, value) return value end end }) end function cvt_to_hand(parms, info, in_current, out_current) -- Convert input to hands, inches. -- Return true, t where t is a table with the conversion results; -- or return false, t where t is an error message table. if parms.abbr_org == nil then out_current.usename = true -- default is to show name not symbol end local precision = parms.precision local frac = out_current.frac if not frac and precision and precision > 1 then frac = (precision == 2) and 2 or 4 end local out_next = out_current.out_next if out_next then -- Use magic knowledge to determine whether the next unit is inches without requiring i18n. -- The following ensures that when the output combination "hand in" is used, the inches -- value is rounded to match the hands value. Also, displaying say "61½" instead of 61.5 -- is better as 61.5 implies the value is not 61.4. if out_next.exception == 'subunit_more_precision' then out_next.frac = frac end end -- Convert to inches; calculate hands from that. local dummy_unit_table = { scale = out_current.scale / 4, frac = frac } local success, outinfo = cvtround(parms, info, in_current, dummy_unit_table) if not success then return false, outinfo end local tfrac = outinfo.fraction_table local inches = outinfo.raw_absvalue if tfrac then inches = floor(inches) -- integer part only; fraction added later else inches = floor(inches + 0.5) -- a hands measurement never shows decimals of an inch end local hands, inches = divide(inches, 4) outinfo.absvalue = hands + inches/4 -- supposed to be the absolute rounded value, but this is close enough local inchstr = tostring(inches) -- '0', '1', '2' or '3' if precision and precision <= 0 then -- using negative or 0 for precision rounds to nearest hand hands = floor(outinfo.raw_absvalue/4 + 0.5) inchstr = '' elseif tfrac then -- Always show an integer before fraction (like "15.0½") because "15½" means 15-and-a-half hands. inchstr = numdot .. format_fraction(parms, 'out', false, inchstr, tfrac.numstr, tfrac.denstr) else inchstr = numdot .. from_en(inchstr) end outinfo.show = outinfo.sign .. with_separator(parms, format('%.0f', hands)) .. inchstr return true, outinfo end local function evaluate_condition(value, condition) -- Return true or false from applying a conditional expression to value, -- or throw an error if invalid. -- A very limited set of expressions is supported: -- v < 9 -- v * 9 < 9 -- where -- 'v' is replaced with value -- 9 is any number (as defined by Lua tonumber) -- only en digits are accepted -- '<' can also be '<=' or '>' or '>=' -- In addition, the following form is supported: -- LHS and RHS -- where -- LHS, RHS = any of above expressions. local function compare(value, text) local arithop, factor, compop, limit = text:match('^%s*v%s*([*]?)(.-)([<>]=?)(.*)$') if arithop == nil then error('Invalid default expression', 0) elseif arithop == '*' then factor = tonumber(factor) if factor == nil then error('Invalid default expression', 0) end value = value * factor end limit = tonumber(limit) if limit == nil then error('Invalid default expression', 0) end if compop == '<' then return value < limit elseif compop == '<=' then return value <= limit elseif compop == '>' then return value > limit elseif compop == '>=' then return value >= limit end error('Invalid default expression', 0) -- should not occur end local lhs, rhs = condition:match('^(.-%W)and(%W.*)') if lhs == nil then return compare(value, condition) end return compare(value, lhs) and compare(value, rhs) end local function get_default(value, unit_table) -- Return true, s where s = name of unit's default output unit, -- or return false, t where t is an error message table. -- Some units have a default that depends on the input value -- (the first value if a range of values is used). -- If '!' is in the default, the first bang-delimited field is an -- expression that uses 'v' to represent the input value. -- Example: 'v < 120 ! small ! big ! suffix' (suffix is optional) -- evaluates 'v < 120' as a boolean with result -- 'smallsuffix' if (value < 120), or 'bigsuffix' otherwise. -- Input must use en digits and '.' decimal mark. local default = data_code.default_exceptions[unit_table.defkey or unit_table.symbol] or unit_table.default if not default then local per = unit_table.per if per then local function a_default(v, u) local success, ucode = get_default(v, u) if not success then return '?' -- an unlikely error has occurred; will cause lookup of default to fail end -- Attempt to use only the first unit if a combination or output multiple. -- This is not bulletproof but should work for most cases. -- Where it does not work, the convert will need to specify the wanted output unit. local t = all_units[ucode] if t then local combo = t.combination if combo then -- For a multiple like ftin, the "first" unit (ft) is last in the combination. local i = t.multiple and table_len(combo) or 1 ucode = combo[i] end else -- Try for an automatically generated combination. local item = ucode:match('^(.-)%+') or ucode:match('^(%S+)%s') if all_units[item] then return item end end return ucode end local unit1, unit2 = per[1], per[2] local def1 = (unit1 and a_default(value, unit1) or unit_table.vprefix or '') local def2 = a_default(1, unit2) -- 1 because per unit of denominator return true, def1 .. '/' .. def2 end return false, { 'cvt_no_default', unit_table.symbol } end if default:find('!', 1, true) == nil then return true, default end local t = split(default, '!') if #t == 3 or #t == 4 then local success, result = pcall(evaluate_condition, value, t[1]) if success then default = result and t[2] or t[3] if #t == 4 then default = default .. t[4] end return true, default end end return false, { 'cvt_bad_default', unit_table.symbol } end local linked_pages -- to record linked pages so will not link to the same page more than once local function unlink(unit_table) -- Forget that the given unit has previously been linked (if it has). -- That is needed when processing a range of inputs or outputs when an id -- for the first range value may have been evaluated, but only an id for -- the last value is displayed, and that id may need to be linked. linked_pages[unit_table.unitcode or unit_table] = nil end local function make_link(link, id, unit_table) -- Return wikilink "[[link|id]]", possibly abbreviated as in examples: -- [[Mile|mile]] --> [[mile]] -- [[Mile|miles]] --> [[mile]]s -- However, just id is returned if: -- * no link given (so caller does not need to check if a link was defined); or -- * link has previously been used during the current convert (to avoid overlinking). local link_key if unit_table then link_key = unit_table.unitcode or unit_table else link_key = link end if not link or link == '' or linked_pages[link_key] then return id end linked_pages[link_key] = true -- Following only works for language en, but it should be safe on other wikis, -- and overhead of doing it generally does not seem worthwhile. local l = link:sub(1, 1):lower() .. link:sub(2) if link == id or l == id then return '[[' .. id .. ']]' elseif link .. 's' == id or l .. 's' == id then return '[[' .. id:sub(1, -2) .. ']]s' else return '[[' .. link .. '|' .. id .. ']]' end end local function variable_name(clean, unit_table) -- For slwiki, a unit name depends on the value. -- Parameter clean is the unsigned rounded value in en digits, as a string. -- Value Source Example for "m" -- integer 1: name1 meter (also is the name of the unit) -- integer 2: var{1} metra -- integer 3 and 4: var{2} metri -- integer else: var{3} metrov (0 and 5 or more) -- real/fraction: var{4} metra -- var{i} means the i'th field in unit_table.varname if it exists and has -- an i'th field, otherwise name2. -- Fields are separated with "!" and are not empty. -- A field for a unit using an SI prefix has the prefix name inserted, -- replacing '#' if found, or before the field otherwise. local vname if clean == '1' then vname = unit_table.name1 elseif unit_table.varname then local i if clean == '2' then i = 1 elseif clean == '3' or clean == '4' then i = 2 elseif clean:find('.', 1, true) then i = 4 else i = 3 end if i > 1 and varname == 'pl' then i = i - 1 end vname = split(unit_table.varname, '!')[i] end if vname then local si_name = rawget(unit_table, 'si_name') or '' local pos = vname:find('#', 1, true) if pos then vname = vname:sub(1, pos - 1) .. si_name .. vname:sub(pos + 1) else vname = si_name .. vname end return vname end return unit_table.name2 end local function linked_id(parms, unit_table, key_id, want_link, clean) -- Return final unit id (symbol or name), optionally with a wikilink, -- and update unit_table.sep if required. -- key_id is one of: 'symbol', 'sym_us', 'name1', 'name1_us', 'name2', 'name2_us'. local abbr_on = (key_id == 'symbol' or key_id == 'sym_us') if abbr_on and want_link then local symlink = rawget(unit_table, 'symlink') if symlink then return symlink -- for exceptions that have the linked symbol built-in end end local multiplier = rawget(unit_table, 'multiplier') local per = unit_table.per if per then local paren1, paren2 = '', '' -- possible parentheses around bottom unit local unit1 = per[1] -- top unit_table, or nil local unit2 = per[2] -- bottom unit_table if abbr_on then if not unit1 then unit_table.sep = '' -- no separator in "$2/acre" end if not want_link then local symbol = unit_table.symbol_raw if symbol then return symbol -- for exceptions that have the symbol built-in end end if (unit2.symbol):find('⋅', 1, true) then paren1, paren2 = '(', ')' end end local key_id2 -- unit2 is always singular if key_id == 'name2' then key_id2 = 'name1' elseif key_id == 'name2_us' then key_id2 = 'name1_us' else key_id2 = key_id end local result if abbr_on then result = '/' elseif omitsep then result = per_word elseif unit1 then result = ' ' .. per_word .. ' ' else result = per_word .. ' ' end if want_link and unit_table.link then if abbr_on or not varname then result = (unit1 and linked_id(parms, unit1, key_id, false, clean) or '') .. result .. linked_id(parms, unit2, key_id2, false, '1') else result = (unit1 and variable_name(clean, unit1) or '') .. result .. variable_name('1', unit2) end if omit_separator(result) then unit_table.sep = '' end return make_link(unit_table.link, result, unit_table) end if unit1 then result = linked_id(parms, unit1, key_id, want_link, clean) .. result if unit1.sep then unit_table.sep = unit1.sep end elseif omitsep then unit_table.sep = '' end return result .. paren1 .. linked_id(parms, unit2, key_id2, want_link, '1') .. paren2 end if multiplier then -- A multiplier (like "100" in "100km") forces the unit to be plural. multiplier = from_en(multiplier) if not omitsep then multiplier = multiplier .. (abbr_on and '&nbsp;' or ' ') end if not abbr_on then if key_id == 'name1' then key_id = 'name2' elseif key_id == 'name1_us' then key_id = 'name2_us' end end else multiplier = '' end local id = unit_table.fixed_name or ((varname and not abbr_on) and variable_name(clean, unit_table) or unit_table[key_id]) if omit_separator(id) then unit_table.sep = '' end if want_link then local link = data_code.link_exceptions[unit_table.linkey or unit_table.symbol] or unit_table.link if link then local before = '' local i = unit_table.customary if i == 1 and parms.opt_sp_us then i = 2 -- show "U.S." not "US" end if i == 3 and abbr_on then i = 4 -- abbreviate "imperial" to "imp" end local customary = text_code.customary_units[i] if customary then -- LATER: This works for language en only, but it's esoteric so ignore for now. local pertext if id:sub(1, 1) == '/' then -- Want unit "/USgal" to display as "/U.S. gal", not "U.S. /gal". pertext = '/' id = id:sub(2) elseif id:sub(1, 4) == 'per ' then -- Similarly want "per U.S. gallon", not "U.S. per gallon" (but in practice this is unlikely to be used). pertext = 'per ' id = id:sub(5) else pertext = '' end -- Omit any "US"/"U.S."/"imp"/"imperial" from start of id since that will be inserted. local removes = (i < 3) and { 'US&nbsp;', 'US ', 'U.S.&nbsp;', 'U.S. ' } or { 'imp&nbsp;', 'imp ', 'imperial ' } for _, prefix in ipairs(removes) do local plen = #prefix if id:sub(1, plen) == prefix then id = id:sub(plen + 1) break end end before = pertext .. make_link(customary.link, customary[1]) .. ' ' end id = before .. make_link(link, id, unit_table) end end return multiplier .. id end local function make_id(parms, which, unit_table) -- Return id, f where -- id = unit name or symbol, possibly modified -- f = true if id is a name, or false if id is a symbol -- using the value for index 'which', and for 'in' or 'out' (unit_table.inout). -- Result is '' if no symbol/name is to be used. -- In addition, set unit_table.sep = ' ' or '&nbsp;' or '' -- (the separator that caller will normally insert before the id). if parms.opt_values then unit_table.sep = '' return '' end local inout = unit_table.inout local info = unit_table.valinfo[which] local abbr_org = parms.abbr_org local adjectival = parms.opt_adjectival local lk = parms.lk local want_link = (lk == 'on' or lk == inout) local usename = unit_table.usename local singular = info.singular local want_name if usename then want_name = true else if abbr_org == nil then if parms.wantname then want_name = true end if unit_table.usesymbol then want_name = false end end if want_name == nil then local abbr = parms.abbr if abbr == 'on' or abbr == inout or (abbr == 'mos' and inout == 'out') then want_name = false else want_name = true end end end local key if want_name then if lk == nil and unit_table.builtin == 'hand' then want_link = true end if parms.opt_use_nbsp then unit_table.sep = '&nbsp;' else unit_table.sep = ' ' end if parms.opt_singular then local value if inout == 'in' then value = info.value else value = info.absvalue end if value then -- some unusual units do not always set value field value = abs(value) singular = (0 < value and value < 1.0001) end end if unit_table.engscale then -- engscale: so "|1|e3kg" gives "1 thousand kilograms" (plural) singular = false end key = (adjectival or singular) and 'name1' or 'name2' if parms.opt_sp_us then key = key .. '_us' end else if unit_table.builtin == 'hand' then if parms.opt_hand_hh then unit_table.symbol = 'hh' -- LATER: might want i18n applied to this end end unit_table.sep = '&nbsp;' key = parms.opt_sp_us and 'sym_us' or 'symbol' end return linked_id(parms, unit_table, key, want_link, info.clean), want_name end local function decorate_value(parms, unit_table, which, number_word) -- If needed, update unit_table so values will be shown with extra information. -- For consistency with the old template (but different from fmtpower), -- the style to display powers of 10 includes "display:none" to allow some -- browsers to copy, for example, "10³" as "10^3", rather than as "103". local info local engscale = unit_table.engscale local prefix = unit_table.vprefix if engscale or prefix then info = unit_table.valinfo[which] if info.decorated then return -- do not redecorate if repeating convert end info.decorated = true if engscale then local inout = unit_table.inout local abbr = parms.abbr if (abbr == 'on' or abbr == inout) and not parms.number_word then info.show = info.show .. '<span style="margin-left:0.2em">×<span style="margin-left:0.1em">' .. from_en('10') .. '</span></span><s style="display:none">^</s><sup>' .. from_en(tostring(engscale.exponent)) .. '</sup>' elseif number_word then local number_id local lk = parms.lk if lk == 'on' or lk == inout then number_id = make_link(engscale.link, engscale[1]) else number_id = engscale[1] end -- WP:NUMERAL recommends "&nbsp;" in values like "12 million". info.show = info.show .. (parms.opt_adjectival and '-' or '&nbsp;') .. number_id end end if prefix then info.show = prefix .. info.show end end end local function process_input(parms, in_current) -- Processing required once per conversion. -- Return block of text to represent input (value/unit). if parms.opt_output_only or parms.opt_output_number_only or parms.opt_output_unit_only then parms.joins = { '', '' } return '' end local first_unit local composite = in_current.composite -- nil or table of units if composite then first_unit = composite[1] else first_unit = in_current end local id1, want_name = make_id(parms, 1, first_unit) local sep = first_unit.sep -- separator between value and unit, set by make_id local preunit = parms.preunit1 if preunit then sep = '' -- any separator is included in preunit else preunit = '' end if parms.opt_input_unit_only then parms.joins = { '', '' } if composite then local parts = { id1 } for i, unit in ipairs(composite) do if i > 1 then table.insert(parts, (make_id(parms, 1, unit))) end end id1 = table.concat(parts, ' ') end if want_name and parms.opt_adjectival then return preunit .. hyphenated(id1) end return preunit .. id1 end if parms.opt_also_symbol and not composite and not parms.opt_flip then local join1 = parms.joins[1] if join1 == ' (' or join1 == ' [' then parms.joins = { ' [' .. first_unit[parms.opt_sp_us and 'sym_us' or 'symbol'] .. ']' .. join1 , parms.joins[2] } end end if in_current.builtin == 'mach' and first_unit.sep ~= '' then -- '' means omitsep with non-enwiki name local prefix = id1 .. '&nbsp;' local range = parms.range local valinfo = first_unit.valinfo local result = prefix .. valinfo[1].show if range then -- For simplicity and because more not needed, handle one range item only. local prefix2 = make_id(parms, 2, first_unit) .. '&nbsp;' result = range_text(range[1], want_name, parms, result, prefix2 .. valinfo[2].show, 'in', {spaced=true}) end return preunit .. result end if composite then -- Simplify: assume there is no range, and no decoration. local mid = (not parms.opt_flip) and parms.mid or '' local sep1 = '&nbsp;' local sep2 = ' ' if parms.opt_adjectival and want_name then sep1 = '-' sep2 = '-' end if omitsep and sep == '' then -- Testing the id of the most significant unit should be sufficient. sep1 = '' sep2 = '' end local parts = { first_unit.valinfo[1].show .. sep1 .. id1 } for i, unit in ipairs(composite) do if i > 1 then table.insert(parts, unit.valinfo[1].show .. sep1 .. (make_id(parms, 1, unit))) end end return table.concat(parts, sep2) .. mid end local add_unit = (parms.abbr == 'mos') or parms[parms.opt_flip and 'out_range_x' or 'in_range_x'] or (not want_name and parms.abbr_range_x) local range = parms.range if range and not add_unit then unlink(first_unit) end local id = range and make_id(parms, range.n + 1, first_unit) or id1 local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, 'in') if was_hyphenated then add_unit = false end local result local valinfo = first_unit.valinfo if range then for i = 0, range.n do local number_word if i == range.n then add_unit = false number_word = true end decorate_value(parms, first_unit, i+1, number_word) local show = valinfo[i+1].show if add_unit then show = show .. first_unit.sep .. (i == 0 and id1 or make_id(parms, i+1, first_unit)) end if i == 0 then result = show else result = range_text(range[i], want_name, parms, result, show, 'in') end end else decorate_value(parms, first_unit, 1, true) result = valinfo[1].show end return result .. preunit .. extra end local function process_one_output(parms, out_current) -- Processing required for each output unit. -- Return block of text to represent output (value/unit). local inout = out_current.inout -- normally 'out' but can be 'in' for order=out local id1, want_name = make_id(parms, 1, out_current) local sep = out_current.sep -- set by make_id local preunit = parms.preunit2 if preunit then sep = '' -- any separator is included in preunit else preunit = '' end if parms.opt_output_unit_only then if want_name and parms.opt_adjectival then return preunit .. hyphenated(id1) end return preunit .. id1 end if out_current.builtin == 'mach' and out_current.sep ~= '' then -- '' means omitsep with non-enwiki name local prefix = id1 .. '&nbsp;' local range = parms.range local valinfo = out_current.valinfo local result = prefix .. valinfo[1].show if range then -- For simplicity and because more not needed, handle one range item only. result = range_text(range[1], want_name, parms, result, prefix .. valinfo[2].show, inout, {spaced=true}) end return preunit .. result end local add_unit = (parms[parms.opt_flip and 'in_range_x' or 'out_range_x'] or (not want_name and parms.abbr_range_x)) and not parms.opt_output_number_only local range = parms.range if range and not add_unit then unlink(out_current) end local id = range and make_id(parms, range.n + 1, out_current) or id1 local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, inout) if was_hyphenated then add_unit = false end local result local valinfo = out_current.valinfo if range then for i = 0, range.n do local number_word if i == range.n then add_unit = false number_word = true end decorate_value(parms, out_current, i+1, number_word) local show = valinfo[i+1].show if add_unit then show = show .. out_current.sep .. (i == 0 and id1 or make_id(parms, i+1, out_current)) end if i == 0 then result = show else result = range_text(range[i], want_name, parms, result, show, inout) end end else decorate_value(parms, out_current, 1, true) result = valinfo[1].show end if parms.opt_output_number_only then return result end return result .. preunit .. extra end local function make_output_single(parms, in_unit_table, out_unit_table) -- Return true, item where item = wikitext of the conversion result -- for a single output (which is not a combination or a multiple); -- or return false, t where t is an error message table. if parms.opt_order_out and in_unit_table.unitcode == out_unit_table.unitcode then out_unit_table.valinfo = in_unit_table.valinfo else out_unit_table.valinfo = collection() for _, v in ipairs(in_unit_table.valinfo) do local success, info = cvtround(parms, v, in_unit_table, out_unit_table) if not success then return false, info end out_unit_table.valinfo:add(info) end end return true, process_one_output(parms, out_unit_table) end local function make_output_multiple(parms, in_unit_table, out_unit_table) -- Return true, item where item = wikitext of the conversion result -- for an output which is a multiple (like 'ftin'); -- or return false, t where t is an error message table. local inout = out_unit_table.inout -- normally 'out' but can be 'in' for order=out local multiple = out_unit_table.multiple -- table of scaling factors (will not be nil) local combos = out_unit_table.combination -- table of unit tables (will not be nil) local abbr = parms.abbr local abbr_org = parms.abbr_org local disp = parms.disp local want_name = (abbr_org == nil and (disp == 'or' or disp == 'slash')) or not (abbr == 'on' or abbr == inout or abbr == 'mos') local want_link = (parms.lk == 'on' or parms.lk == inout) local mid = parms.opt_flip and parms.mid or '' local sep1 = '&nbsp;' local sep2 = ' ' if parms.opt_adjectival and want_name then sep1 = '-' sep2 = '-' end local do_spell = parms.opt_spell_out parms.opt_spell_out = nil -- so the call to cvtround does not spell the value local function make_result(info, isfirst) local fmt, outvalue, sign local results = {} for i = 1, #combos do local tfrac, thisvalue, strforce local out_current = combos[i] out_current.inout = inout local scale = multiple[i] if i == 1 then -- least significant unit ('in' from 'ftin') local decimals out_current.frac = out_unit_table.frac local success, outinfo = cvtround(parms, info, in_unit_table, out_current) if not success then return false, outinfo end if isfirst then out_unit_table.valinfo = { outinfo } -- in case output value of first least significant unit is needed end sign = outinfo.sign tfrac = outinfo.fraction_table if outinfo.is_scientific then strforce = outinfo.show decimals = '' elseif tfrac then decimals = '' else local show = outinfo.show -- number as a string in local language local p1, p2 = show:find(numdot, 1, true) decimals = p1 and show:sub(p2 + 1) or '' -- text after numdot, if any end fmt = '%.' .. ulen(decimals) .. 'f' -- to reproduce precision if decimals == '' then if tfrac then outvalue = floor(outinfo.raw_absvalue) -- integer part only; fraction added later else outvalue = floor(outinfo.raw_absvalue + 0.5) -- keep all integer digits of least significant unit end else outvalue = outinfo.absvalue end end if scale then outvalue, thisvalue = divide(outvalue, scale) else thisvalue = outvalue end local id if want_name then if varname then local clean if strforce or tfrac then clean = '.1' -- dummy value to force name for floating point else clean = format(fmt, thisvalue) end id = variable_name(clean, out_current) else local key = 'name2' if parms.opt_adjectival then key = 'name1' elseif tfrac then if thisvalue == 0 then key = 'name1' end elseif parms.opt_singular then if 0 < thisvalue and thisvalue < 1.0001 then key = 'name1' end else if thisvalue == 1 then key = 'name1' end end id = out_current[key] end else id = out_current['symbol'] end if i == 1 and omit_separator(id) then -- Testing the id of the least significant unit should be sufficient. sep1 = '' sep2 = '' end if want_link then local link = out_current.link if link then id = make_link(link, id, out_current) end end local strval local spell_inout = (i == #combos or outvalue == 0) and inout or '' -- trick so the last value processed (first displayed) has uppercase, if requested if strforce and outvalue == 0 then sign = '' -- any sign is in strforce strval = strforce -- show small values in scientific notation; will only use least significant unit elseif tfrac then local wholestr = (thisvalue > 0) and tostring(thisvalue) or nil strval = format_fraction(parms, spell_inout, false, wholestr, tfrac.numstr, tfrac.denstr, do_spell) else strval = (thisvalue == 0) and from_en('0') or with_separator(parms, format(fmt, thisvalue)) if do_spell then strval = spell_number(parms, spell_inout, strval) or strval end end table.insert(results, strval .. sep1 .. id) if outvalue == 0 then break end fmt = '%.0f' -- only least significant unit can have a non-integral value end local reversed, count = {}, #results for i = 1, count do reversed[i] = results[count + 1 - i] end return true, sign .. table.concat(reversed, sep2) end local valinfo = in_unit_table.valinfo local success, result = make_result(valinfo[1], true) if not success then return false, result end local range = parms.range if range then for i = 1, range.n do local success, result2 = make_result(valinfo[i+1]) if not success then return false, result2 end result = range_text(range[i], want_name, parms, result, result2, inout, {spaced=true}) end end return true, result .. mid end local function process(parms, in_unit_table, out_unit_table) -- Return true, s, outunit where s = final wikitext result, -- or return false, t where t is an error message table. linked_pages = {} local success, bad_output local bad_input_mcode = in_unit_table.bad_mcode -- nil if input unit is a valid convert unit local out_unit = parms.out_unit if out_unit == nil or out_unit == '' or type(out_unit) == 'function' then if bad_input_mcode or parms.opt_input_unit_only then bad_output = '' else local getdef = type(out_unit) == 'function' and out_unit or get_default success, out_unit = getdef(in_unit_table.valinfo[1].value, in_unit_table) parms.out_unit = out_unit if not success then bad_output = out_unit end end end if not bad_output and not out_unit_table then success, out_unit_table = lookup(parms, out_unit, 'any_combination') if success then local mismatch = check_mismatch(in_unit_table, out_unit_table) if mismatch then bad_output = mismatch end else bad_output = out_unit_table end end local lhs, rhs local flipped = parms.opt_flip and not bad_input_mcode if bad_output then rhs = (bad_output == '') and '' or message(parms, bad_output) elseif parms.opt_input_unit_only then rhs = '' else local combos -- nil (for 'ft' or 'ftin'), or table of unit tables (for 'm ft') if not out_unit_table.multiple then -- nil/false ('ft' or 'm ft'), or table of factors ('ftin') combos = out_unit_table.combination end local frac = parms.frac -- nil or denominator of fraction for output values if frac then -- Apply fraction to the unit (if only one), or to non-SI units (if a combination), -- except that if a precision is also specified, the fraction only applies to -- the hand unit; that allows the following result: -- {{convert|156|cm|in hand|1|frac=2}} → 156 centimetres (61.4 in; 15.1½ hands) -- However, the following is handled elsewhere as a special case: -- {{convert|156|cm|hand in|1|frac=2}} → 156 centimetres (15.1½ hands; 61½ in) if combos then local precision = parms.precision for _, unit in ipairs(combos) do if unit.builtin == 'hand' or (not precision and not unit.prefixes) then unit.frac = frac end end else out_unit_table.frac = frac end end local outputs = {} local imax = combos and #combos or 1 -- 1 (single unit) or number of unit tables if imax == 1 then parms.opt_order_out = nil -- only useful with an output combination end if not flipped and not parms.opt_order_out then -- Process left side first so any duplicate links (from lk=on) are suppressed -- on right. Example: {{convert|28|e9pc|e9ly|abbr=off|lk=on}} lhs = process_input(parms, in_unit_table) end for i = 1, imax do local success, item local out_current = combos and combos[i] or out_unit_table out_current.inout = 'out' if i == 1 then if imax > 1 and out_current.builtin == 'hand' then out_current.out_next = combos[2] -- built-in hand can influence next unit in a combination end if parms.opt_order_out then out_current.inout = 'in' end end if out_current.multiple then success, item = make_output_multiple(parms, in_unit_table, out_current) else success, item = make_output_single(parms, in_unit_table, out_current) end if not success then return false, item end outputs[i] = item end if parms.opt_order_out then lhs = outputs[1] table.remove(outputs, 1) end local sep = parms.table_joins and parms.table_joins[2] or parms.join_between rhs = table.concat(outputs, sep) end if flipped or not lhs then local input = process_input(parms, in_unit_table) if flipped then lhs = rhs rhs = input else lhs = input end end if parms.join_before then lhs = parms.join_before .. lhs end local wikitext if bad_input_mcode then if bad_input_mcode == '' then wikitext = lhs else wikitext = lhs .. message(parms, bad_input_mcode) end elseif parms.table_joins then wikitext = parms.table_joins[1] .. lhs .. parms.table_joins[2] .. rhs else wikitext = lhs .. parms.joins[1] .. rhs .. parms.joins[2] end if parms.warnings and not bad_input_mcode then wikitext = wikitext .. parms.warnings end return true, get_styles(parms) .. wikitext, out_unit_table end local function main_convert(frame) -- Do convert, and if needed, do it again with higher default precision. local parms = { frame = frame } -- will hold template arguments, after translation set_config(frame.args) local success, result = get_parms(parms, frame:getParent().args) if success then if type(result) ~= 'table' then return tostring(result) end local in_unit_table = result local out_unit_table for _ = 1, 2 do -- use counter so cannot get stuck repeating convert success, result, out_unit_table = process(parms, in_unit_table, out_unit_table) if success and parms.do_convert_again then parms.do_convert_again = false else break end end end -- If input=x gives a problem, the result should be just the user input -- (if x is a property like P123 it has been replaced with ''). -- An unknown input unit would display the input and an error message -- with success == true at this point. -- Also, can have success == false with a message that outputs an empty string. if parms.input_text then if success and not parms.have_problem then return result end local cat if parms.tracking then -- Add a tracking category using the given text as the category sort key. -- There is currently only one type of tracking, but in principle multiple -- items could be tracked, using different sort keys for convenience. cat = wanted_category('tracking', parms.tracking) end return parms.input_text .. (cat or '') end return success and result or message(parms, result) end local function _unit(unitcode, options) -- Helper function for Module:Val to look up a unit. -- Parameter unitcode must be a string to identify the wanted unit. -- Parameter options must be nil or a table with optional fields: -- value = number (for sort key; default value is 1) -- scaled_top = nil for a normal unit, or a number for a unit which is -- the denominator of a per unit (for sort key) -- si = { 'symbol', 'link' } -- (a table with two strings) to make an SI unit -- that will be used for the look up -- link = true if result should be [[linked]] -- sort = 'on' or 'debug' if result should include a sort key in a -- span element ('debug' makes the key visible) -- name = true for the name of the unit instead of the symbol -- us = true for the US spelling of the unit, if any -- Return nil if unitcode is not a non-empty string. -- Otherwise return a table with fields: -- text = requested symbol or name of unit, optionally linked -- scaled_value = input value adjusted by unit scale; used for sort key -- sortspan = span element with sort key like that provided by {{ntsh}}, -- calculated from the result of converting value -- to a base unit with scale 1. -- unknown = true if the unitcode was not known unitcode = strip(unitcode) if unitcode == nil or unitcode == '' then return nil end set_config({}) linked_pages = {} options = options or {} local parms = { abbr = options.name and 'off' or 'on', lk = options.link and 'on' or nil, opt_sp_us = options.us and true or nil, opt_ignore_error = true, -- do not add pages using this function to 'what links here' for Module:Convert/extra opt_sortable_on = options.sort == 'on' or options.sort == 'debug', opt_sortable_debug = options.sort == 'debug', } if options.si then -- Make a dummy table of units (just one unit) for lookup to use. -- This makes lookup recognize any SI prefix in the unitcode. local symbol = options.si[1] or '?' parms.unittable = { [symbol] = { _name1 = symbol, _name2 = symbol, _symbol = symbol, utype = symbol, scale = symbol == 'g' and 0.001 or 1, prefixes = 1, default = symbol, link = options.si[2], }} end local success, unit_table = lookup(parms, unitcode, 'no_combination') if not success then unit_table = setmetatable({ symbol = unitcode, name2 = unitcode, utype = unitcode, scale = 1, default = '', defkey = '', linkey = '' }, unit_mt) end local value = tonumber(options.value) or 1 local clean = tostring(abs(value)) local info = { value = value, altvalue = value, singular = (clean == '1'), clean = clean, show = clean, } unit_table.inout = 'in' unit_table.valinfo = { info } local sortspan, scaled_value if options.sort then sortspan, scaled_value = make_table_or_sort(parms, value, info, unit_table, options.scaled_top) end return { text = make_id(parms, 1, unit_table), sortspan = sortspan, scaled_value = scaled_value, unknown = not success and true or nil, } end return { convert = main_convert, _unit = _unit } da3d419635c73ffef0a5bcc2a7d6620979271521 Module:Convert/data 828 47 109 2022-02-13T04:01:16Z Canopus >Johnuniq 0 update from sandbox per [[Template talk:Convert#Module version 27]] Scribunto text/plain -- Conversion data used by [[Module:Convert]] which uses mw.loadData() for -- read-only access to this module so that it is loaded only once per page. -- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki. -- -- These data tables follow: -- all_units all properties for a unit, including default output -- default_exceptions exceptions for default output ('kg' and 'g' have different defaults) -- link_exceptions exceptions for links ('kg' and 'g' have different links) -- -- These tables are generated by a script which reads the wikitext of a page that -- documents the required properties of each unit; see [[:en:Module:Convert/doc]]. --------------------------------------------------------------------------- -- Do not change the data in this table because it is created by running -- -- a script that reads the wikitext from a wiki page (see note above). -- --------------------------------------------------------------------------- local all_units = { ["Gy"] = { _name1 = "gray", _symbol = "Gy", utype = "absorbed radiation dose", scale = 1, prefixes = 1, default = "rad", link = "Gray (unit)", }, ["rad"] = { _name1 = "rad", _symbol = "rad", utype = "absorbed radiation dose", scale = 0.01, prefixes = 1, default = "Gy", link = "Rad (unit)", }, ["cm/s2"] = { name1 = "centimetre per second squared", name1_us = "centimeter per second squared", name2 = "centimetres per second squared", name2_us = "centimeters per second squared", symbol = "cm/s<sup>2</sup>", utype = "acceleration", scale = 0.01, default = "ft/s2", link = "Gal (unit)", }, ["ft/s2"] = { name1 = "foot per second squared", name2 = "feet per second squared", symbol = "ft/s<sup>2</sup>", utype = "acceleration", scale = 0.3048, default = "m/s2", }, ["g0"] = { name1 = "standard gravity", name2 = "standard gravities", symbol = "''g''<sub>0</sub>", utype = "acceleration", scale = 9.80665, default = "m/s2", }, ["g-force"] = { name2 = "''g''", symbol = "''g''", utype = "acceleration", scale = 9.80665, default = "m/s2", link = "g-force", }, ["km/hs"] = { name1 = "kilometre per hour per second", name1_us = "kilometer per hour per second", name2 = "kilometres per hour per second", name2_us = "kilometers per hour per second", symbol = "km/(h⋅s)", utype = "acceleration", scale = 0.27777777777777779, default = "mph/s", link = "Acceleration", }, ["km/s2"] = { name1 = "kilometre per second squared", name1_us = "kilometer per second squared", name2 = "kilometres per second squared", name2_us = "kilometers per second squared", symbol = "km/s<sup>2</sup>", utype = "acceleration", scale = 1000, default = "mph/s", link = "Acceleration", }, ["m/s2"] = { name1 = "metre per second squared", name1_us = "meter per second squared", name2 = "metres per second squared", name2_us = "meters per second squared", symbol = "m/s<sup>2</sup>", utype = "acceleration", scale = 1, default = "ft/s2", }, ["mph/s"] = { name1 = "mile per hour per second", name2 = "miles per hour per second", symbol = "mph/s", utype = "acceleration", scale = 0.44704, default = "km/hs", link = "Acceleration", }, ["km/h/s"] = { target = "km/hs", }, ["standard gravity"] = { target = "g0", }, ["1000sqft"] = { name1 = "thousand square feet", name2 = "thousand square feet", symbol = "1000&nbsp;sq&nbsp;ft", utype = "area", scale = 92.90304, default = "m2", link = "Square foot", }, ["a"] = { _name1 = "are", _symbol = "a", utype = "area", scale = 100, prefixes = 1, default = "sqft", link = "Hectare#Are", }, ["acre"] = { symbol = "acre", usename = 1, utype = "area", scale = 4046.8564224, default = "ha", subdivs = { ["rood"] = { 4, default = "ha" }, ["sqperch"] = { 160, default = "ha" } }, }, ["acre-sing"] = { target = "acre", }, ["arpent"] = { symbol = "arpent", usename = 1, utype = "area", scale = 3418.89, default = "ha", }, ["cda"] = { name1 = "cuerda", symbol = "cda", utype = "area", scale = 3930.395625, default = "ha acre", }, ["daa"] = { name1 = "decare", symbol = "daa", utype = "area", scale = 1000, default = "km2 sqmi", }, ["dunam"] = { symbol = "dunam", usename = 1, utype = "area", scale = 1000, default = "km2 sqmi", }, ["dunum"] = { symbol = "dunum", usename = 1, utype = "area", scale = 1000, default = "km2 sqmi", link = "Dunam", }, ["ha"] = { name1 = "hectare", symbol = "ha", utype = "area", scale = 10000, default = "acre", }, ["hectare"] = { name1 = "hectare", symbol = "ha", usename = 1, utype = "area", scale = 10000, default = "acre", }, ["Irish acre"] = { name1 = "Irish acre", symbol = "Irish&nbsp;acres", utype = "area", scale = 6555.2385024, default = "ha", link = "Acre (Irish)", }, ["m2"] = { _name1 = "square metre", _name1_us= "square meter", _symbol = "m<sup>2</sup>", prefix_position= 8, utype = "area", scale = 1, prefixes = 2, default = "sqft", link = "Square metre", }, ["pondemaat"] = { name1 = "pondemaat", name2 = "pondemaat", symbol = "pond", utype = "area", scale = 3674.363358816, default = "m2", link = ":nl:pondemaat", }, ["pyeong"] = { name2 = "pyeong", symbol = "pyeong", usename = 1, utype = "area", scale = 3.3057851239669422, default = "m2", }, ["rai"] = { name2 = "rai", symbol = "rai", utype = "area", scale = 1600, default = "m2", link = "Rai (unit)", }, ["rood"] = { symbol = "rood", usename = 1, utype = "area", scale = 1011.7141056, default = "sqft m2", subdivs = { ["sqperch"] = { 40, default = "m2" } }, link = "Rood (unit)", }, ["sqfoot"] = { name1 = "square foot", name2 = "square foot", symbol = "sq&nbsp;ft", utype = "area", scale = 0.09290304, default = "m2", }, ["sqft"] = { name1 = "square foot", name2 = "square feet", symbol = "sq&nbsp;ft", utype = "area", scale = 0.09290304, default = "m2", }, ["sqin"] = { name1 = "square inch", name2 = "square inches", symbol = "sq&nbsp;in", utype = "area", scale = 0.00064516, default = "cm2", }, ["sqmi"] = { name1 = "square mile", symbol = "sq&nbsp;mi", utype = "area", scale = 2589988.110336, default = "km2", }, ["sqnmi"] = { name1 = "square nautical mile", symbol = "sq&nbsp;nmi", utype = "area", scale = 3429904, default = "km2 sqmi", link = "Nautical mile", }, ["sqperch"] = { name2 = "perches", symbol = "perch", usename = 1, utype = "area", scale = 25.29285264, default = "m2", link = "Rod (unit)#Area and volume", }, ["sqverst"] = { symbol = "square verst", usename = 1, utype = "area", scale = 1138062.24, default = "km2 sqmi", link = "Verst", }, ["sqyd"] = { name1 = "square yard", symbol = "sq&nbsp;yd", utype = "area", scale = 0.83612736, default = "m2", }, ["tsubo"] = { name2 = "tsubo", symbol = "tsubo", usename = 1, utype = "area", scale = 3.3057851239669422, default = "m2", link = "Japanese units of measurement#Area", }, ["acres"] = { target = "acre", }, ["are"] = { target = "a", }, ["decare"] = { target = "daa", }, ["foot2"] = { target = "sqfoot", }, ["ft2"] = { target = "sqft", }, ["in2"] = { target = "sqin", symbol = "in<sup>2</sup>", }, ["km²"] = { target = "km2", }, ["mi2"] = { target = "sqmi", }, ["million acre"] = { target = "e6acre", }, ["million acres"] = { target = "e6acre", }, ["million hectares"] = { target = "e6ha", }, ["m²"] = { target = "m2", }, ["nmi2"] = { target = "sqnmi", }, ["pond"] = { target = "pondemaat", }, ["sq arp"] = { target = "arpent", }, ["sqkm"] = { target = "km2", }, ["sqm"] = { target = "m2", }, ["square verst"] = { target = "sqverst", }, ["verst2"] = { target = "sqverst", }, ["yd2"] = { target = "sqyd", }, ["m2/ha"] = { name1 = "square metre per hectare", name1_us = "square meter per hectare", name2 = "square metres per hectare", name2_us = "square meters per hectare", symbol = "m<sup>2</sup>/ha", utype = "area per unit area", scale = 0.0001, default = "sqft/acre", link = "Basal area", }, ["sqft/acre"] = { name1 = "square foot per acre", name2 = "square feet per acre", symbol = "sq&nbsp;ft/acre", utype = "area per unit area", scale = 2.295684113865932e-5, default = "m2/ha", link = "Basal area", }, ["cent"] = { name1 = "cent", symbol = "¢", utype = "cent", scale = 1, default = "cent", link = "Cent (currency)", }, ["¢"] = { target = "cent", }, ["A.h"] = { name1 = "ampere hour", symbol = "A⋅h", utype = "charge", scale = 3600, default = "coulomb", }, ["coulomb"] = { _name1 = "coulomb", _symbol = "C", utype = "charge", scale = 1, prefixes = 1, default = "e", link = "Coulomb", }, ["e"] = { name1 = "elementary charge", symbol = "''e''", utype = "charge", scale = 1.602176487e-19, default = "coulomb", }, ["g-mol"] = { name1 = "gram-mole", symbol = "g&#8209;mol", utype = "chemical amount", scale = 1, default = "lbmol", link = "Mole (unit)", }, ["gmol"] = { name1 = "gram-mole", symbol = "gmol", utype = "chemical amount", scale = 1, default = "lbmol", link = "Mole (unit)", }, ["kmol"] = { name1 = "kilomole", symbol = "kmol", utype = "chemical amount", scale = 1000, default = "lbmol", link = "Mole (unit)", }, ["lb-mol"] = { name1 = "pound-mole", symbol = "lb&#8209;mol", utype = "chemical amount", scale = 453.59237, default = "mol", }, ["lbmol"] = { name1 = "pound-mole", symbol = "lbmol", utype = "chemical amount", scale = 453.59237, default = "mol", }, ["mol"] = { name1 = "mole", symbol = "mol", utype = "chemical amount", scale = 1, default = "lbmol", link = "Mole (unit)", }, ["kgCO2/L"] = { name1 = "kilogram per litre", name1_us = "kilogram per liter", name2 = "kilograms per litre", name2_us = "kilograms per liter", symbol = "kg(CO<sub>2</sub>)/L", utype = "co2 per unit volume", scale = 1000, default = "lbCO2/USgal", link = "Exhaust gas", }, ["lbCO2/USgal"] = { name1 = "pound per US gallon", name2 = "pounds per US gallon", symbol = "lbCO2/US&nbsp;gal", utype = "co2 per unit volume", scale = 119.82642731689663, default = "kgCO2/L", link = "Exhaust gas", }, ["oz/lb"] = { per = { "oz", "lb" }, utype = "concentration", default = "mg/kg", }, ["mg/kg"] = { per = { "mg", "kg" }, utype = "concentration", default = "oz/lb", }, ["g/dm3"] = { name1 = "gram per cubic decimetre", name1_us = "gram per cubic decimeter", name2 = "grams per cubic decimetre", name2_us = "grams per cubic decimeter", symbol = "g/dm<sup>3</sup>", utype = "density", scale = 1, default = "kg/m3", link = "Density", }, ["g/L"] = { name1 = "gram per litre", name1_us = "gram per liter", name2 = "grams per litre", name2_us = "grams per liter", symbol = "g/L", utype = "density", scale = 1, default = "lb/cuin", link = "Density", }, ["g/mL"] = { name1 = "gram per millilitre", name1_us = "gram per milliliter", name2 = "grams per millilitre", name2_us = "grams per milliliter", symbol = "g/mL", utype = "density", scale = 1000, default = "lb/cuin", link = "Density", }, ["g/ml"] = { name1 = "gram per millilitre", name1_us = "gram per milliliter", name2 = "grams per millilitre", name2_us = "grams per milliliter", symbol = "g/ml", utype = "density", scale = 1000, default = "lb/cuin", link = "Density", }, ["kg/dm3"] = { name1 = "kilogram per cubic decimetre", name1_us = "kilogram per cubic decimeter", name2 = "kilograms per cubic decimetre", name2_us = "kilograms per cubic decimeter", symbol = "kg/dm<sup>3</sup>", utype = "density", scale = 1000, default = "lb/cuft", link = "Density", }, ["kg/L"] = { name1 = "kilogram per litre", name1_us = "kilogram per liter", name2 = "kilograms per litre", name2_us = "kilograms per liter", symbol = "kg/L", utype = "density", scale = 1000, default = "lb/USgal", link = "Density", }, ["kg/l"] = { name1 = "kilogram per litre", name1_us = "kilogram per liter", name2 = "kilograms per litre", name2_us = "kilograms per liter", symbol = "kg/l", utype = "density", scale = 1000, default = "lb/USgal", link = "Density", }, ["kg/m3"] = { name1 = "kilogram per cubic metre", name1_us = "kilogram per cubic meter", name2 = "kilograms per cubic metre", name2_us = "kilograms per cubic meter", symbol = "kg/m<sup>3</sup>", utype = "density", scale = 1, default = "lb/cuyd", link = "Density", }, ["lb/cuft"] = { name1 = "pound per cubic foot", name2 = "pounds per cubic foot", symbol = "lb/cu&nbsp;ft", utype = "density", scale = 16.018463373960142, default = "g/cm3", link = "Density", }, ["lb/cuin"] = { name1 = "pound per cubic inch", name2 = "pounds per cubic inch", symbol = "lb/cu&nbsp;in", utype = "density", scale = 27679.904710203122, default = "g/cm3", link = "Density", }, ["lb/cuyd"] = { name1 = "pound per cubic yard", name2 = "pounds per cubic yard", symbol = "lb/cu&nbsp;yd", utype = "density", scale = 0.5932764212577829, default = "kg/m3", link = "Density", }, ["lb/impgal"] = { name1 = "pound per imperial gallon", name2 = "pounds per imperial gallon", symbol = "lb/imp&nbsp;gal", utype = "density", scale = 99.776372663101697, default = "kg/L", link = "Density", }, ["lb/in3"] = { name1 = "pound per cubic inch", name2 = "pounds per cubic inch", symbol = "lb/cu&thinsp;in", utype = "density", scale = 27679.904710203122, default = "g/cm3", link = "Density", }, ["lb/U.S.gal"] = { name1 = "pound per U.S. gallon", name2 = "pounds per U.S. gallon", symbol = "lb/U.S.&nbsp;gal", utype = "density", scale = 119.82642731689663, default = "kg/L", link = "Density", }, ["lb/USbu"] = { name1 = "pound per US bushel", name2 = "pounds per US bushel", symbol = "lb/US&nbsp;bu", utype = "density", scale = 12.871859780974471, default = "kg/m3", link = "Bushel", }, ["lb/USgal"] = { name1 = "pound per US gallon", name2 = "pounds per US gallon", symbol = "lb/US&nbsp;gal", utype = "density", scale = 119.82642731689663, default = "kg/L", link = "Density", }, ["lbm/cuin"] = { name1 = "pound mass per cubic inch", name2 = "pounds mass per cubic inch", symbol = "lbm/cu&thinsp;in", utype = "density", scale = 27679.904710203122, default = "g/cm3", link = "Density", }, ["mg/L"] = { name1 = "milligram per litre", name1_us = "milligram per liter", name2 = "milligrams per litre", name2_us = "milligrams per liter", symbol = "mg/L", utype = "density", scale = 0.001, default = "lb/cuin", link = "Density", }, ["oz/cuin"] = { name1 = "ounce per cubic inch", name2 = "ounces per cubic inch", symbol = "oz/cu&nbsp;in", utype = "density", scale = 1729.9940443876951, default = "g/cm3", link = "Density", }, ["g/cm3"] = { per = { "g", "cm3" }, utype = "density", default = "lb/cuin", }, ["g/m3"] = { per = { "g", "m3" }, utype = "density", default = "lb/cuyd", link = "Density", }, ["Mg/m3"] = { per = { "Mg", "m3" }, utype = "density", default = "lb/cuft", }, ["mg/l"] = { per = { "mg", "l" }, utype = "density", default = "oz/cuin", }, ["μg/dL"] = { per = { "μg", "dL" }, utype = "density", default = "lb/cuin", }, ["μg/l"] = { per = { "μg", "l" }, utype = "density", default = "oz/cuin", }, ["lb/ft3"] = { target = "lb/cuft", }, ["lb/yd3"] = { target = "lb/cuyd", }, ["lbm/in3"] = { target = "lbm/cuin", }, ["mcg/dL"] = { target = "μg/dL", }, ["oz/in3"] = { target = "oz/cuin", }, ["ug/dL"] = { target = "μg/dL", }, ["ug/l"] = { target = "μg/l", }, ["B.O.T.U."] = { name1 = "Board of Trade Unit", symbol = "B.O.T.U.", utype = "energy", scale = 3600000, default = "MJ", link = "Kilowatt-hour", }, ["bboe"] = { name1 = "barrel of oil equivalent", name2 = "barrels of oil equivalent", symbol = "bboe", utype = "energy", scale = 6117863200, default = "GJ", }, ["BOE"] = { name1 = "barrel of oil equivalent", name2 = "barrels of oil equivalent", symbol = "BOE", utype = "energy", scale = 6117863200, default = "GJ", }, ["BTU"] = { name1 = "British thermal unit", symbol = "BTU", utype = "energy", scale = 1055.05585262, default = "kJ", }, ["Btu"] = { name1 = "British thermal unit", symbol = "Btu", utype = "energy", scale = 1055.05585262, default = "kJ", }, ["BTU-39F"] = { name1 = "British thermal unit (39°F)", name2 = "British thermal units (39°F)", symbol = "BTU<sub>39°F</sub>", utype = "energy", scale = 1059.67, default = "kJ", link = "British thermal unit", }, ["Btu-39F"] = { name1 = "British thermal unit (39°F)", name2 = "British thermal units (39°F)", symbol = "Btu<sub>39°F</sub>", utype = "energy", scale = 1059.67, default = "kJ", link = "British thermal unit", }, ["BTU-59F"] = { name1 = "British thermal unit (59°F)", name2 = "British thermal units (59°F)", symbol = "BTU<sub>59°F</sub>", utype = "energy", scale = 1054.804, default = "kJ", link = "British thermal unit", }, ["Btu-59F"] = { name1 = "British thermal unit (59°F)", name2 = "British thermal units (59°F)", symbol = "Btu<sub>59°F</sub>", utype = "energy", scale = 1054.804, default = "kJ", link = "British thermal unit", }, ["BTU-60F"] = { name1 = "British thermal unit (60°F)", name2 = "British thermal units (60°F)", symbol = "BTU<sub>60°F</sub>", utype = "energy", scale = 1054.68, default = "kJ", link = "British thermal unit", }, ["Btu-60F"] = { name1 = "British thermal unit (60°F)", name2 = "British thermal units (60°F)", symbol = "Btu<sub>60°F</sub>", utype = "energy", scale = 1054.68, default = "kJ", link = "British thermal unit", }, ["BTU-63F"] = { name1 = "British thermal unit (63°F)", name2 = "British thermal units (63°F)", symbol = "BTU<sub>63°F</sub>", utype = "energy", scale = 1054.6, default = "kJ", link = "British thermal unit", }, ["Btu-63F"] = { name1 = "British thermal unit (63°F)", name2 = "British thermal units (63°F)", symbol = "Btu<sub>63°F</sub>", utype = "energy", scale = 1054.6, default = "kJ", link = "British thermal unit", }, ["BTU-ISO"] = { name1 = "British thermal unit (ISO)", name2 = "British thermal units (ISO)", symbol = "BTU<sub>ISO</sub>", utype = "energy", scale = 1055.056, default = "kJ", link = "British thermal unit", }, ["Btu-ISO"] = { target = "BTU-ISO", }, ["BTU-IT"] = { name1 = "British thermal unit (IT)", name2 = "British thermal units (IT)", symbol = "BTU<sub>IT</sub>", utype = "energy", scale = 1055.05585262, default = "kJ", link = "British thermal unit", }, ["Btu-IT"] = { name1 = "British thermal unit (IT)", name2 = "British thermal units (IT)", symbol = "Btu<sub>IT</sub>", utype = "energy", scale = 1055.05585262, default = "kJ", link = "British thermal unit", }, ["BTU-mean"] = { name1 = "British thermal unit (mean)", name2 = "British thermal units (mean)", symbol = "BTU<sub>mean</sub>", utype = "energy", scale = 1055.87, default = "kJ", link = "British thermal unit", }, ["Btu-mean"] = { name1 = "British thermal unit (mean)", name2 = "British thermal units (mean)", symbol = "Btu<sub>mean</sub>", utype = "energy", scale = 1055.87, default = "kJ", link = "British thermal unit", }, ["BTU-th"] = { name1 = "British thermal unit (thermochemical)", name2 = "British thermal units (thermochemical)", symbol = "BTU<sub>th</sub>", utype = "energy", scale = 1054.35026444, default = "kJ", link = "British thermal unit", }, ["Btu-th"] = { name1 = "British thermal unit (thermochemical)", name2 = "British thermal units (thermochemical)", symbol = "Btu<sub>th</sub>", utype = "energy", scale = 1054.35026444, default = "kJ", link = "British thermal unit", }, ["Cal"] = { name1 = "calorie", symbol = "Cal", utype = "energy", scale = 4184, default = "kJ", }, ["cal"] = { name1 = "calorie", symbol = "cal", utype = "energy", scale = 4.184, default = "J", }, ["Cal-15"] = { name1 = "Calorie (15°C)", name2 = "Calories (15°C)", symbol = "Cal<sub>15</sub>", utype = "energy", scale = 4185.8, default = "kJ", link = "Calorie", }, ["cal-15"] = { name1 = "calorie (15°C)", name2 = "calories (15°C)", symbol = "cal<sub>15</sub>", utype = "energy", scale = 4.1858, default = "J", link = "Calorie", }, ["Cal-IT"] = { name1 = "Calorie (International Steam Table)", name2 = "Calories (International Steam Table)", symbol = "Cal<sub>IT</sub>", utype = "energy", scale = 4186.8, default = "kJ", link = "Calorie", }, ["cal-IT"] = { name1 = "calorie (International Steam Table)", name2 = "calories (International Steam Table)", symbol = "cal<sub>IT</sub>", utype = "energy", scale = 4.1868, default = "J", link = "Calorie", }, ["Cal-th"] = { name1 = "Calorie (thermochemical)", name2 = "Calories (thermochemical)", symbol = "Cal<sub>th</sub>", utype = "energy", scale = 4184, default = "kJ", link = "Calorie", }, ["cal-th"] = { name1 = "calorie (thermochemical)", name2 = "calories (thermochemical)", symbol = "cal<sub>th</sub>", utype = "energy", scale = 4.184, default = "J", link = "Calorie", }, ["CHU-IT"] = { name1 = "Celsius heat unit (International Table)", name2 = "Celsius heat units (International Table)", symbol = "CHU<sub>IT</sub>", utype = "energy", scale = 1899.100534716, default = "kJ", link = "Conversion of units#Energy", }, ["cufootnaturalgas"] = { name1 = "cubic foot of natural gas", name2 = "cubic foot of natural gas", symbol = "cuftnaturalgas", usename = 1, utype = "energy", scale = 1055055.85262, default = "MJ", link = "Conversion of units#Energy", }, ["cuftnaturalgas"] = { name1 = "cubic foot of natural gas", name2 = "cubic feet of natural gas", symbol = "cuftnaturalgas", usename = 1, utype = "energy", scale = 1055055.85262, default = "MJ", link = "Conversion of units#Energy", }, ["Eh"] = { name1 = "Hartree", symbol = "''E''<sub>h</sub>", utype = "energy", scale = 4.35974417e-18, default = "eV", }, ["erg"] = { symbol = "erg", utype = "energy", scale = 0.0000001, default = "μJ", }, ["eV"] = { name1 = "electronvolt", symbol = "eV", utype = "energy", scale = 1.602176487e-19, default = "aJ", }, ["feV"] = { name1 = "femtoelectronvolt", symbol = "feV", utype = "energy", scale = 1.602176487e-34, default = "yJ", link = "Electronvolt", }, ["foe"] = { symbol = "foe", utype = "energy", scale = 1e44, default = "YJ", link = "Foe (unit)", }, ["ftlb"] = { name1 = "foot-pound", symbol = "ft⋅lb", utype = "energy", alttype = "torque", scale = 1.3558179483314004, default = "J", link = "Foot-pound (energy)", }, ["ftlb-f"] = { name1 = "foot-pound force", name2 = "foot-pounds force", symbol = "ft⋅lb<sub>f</sub>", utype = "energy", alttype = "torque", scale = 1.3558179483314004, default = "J", link = "Foot-pound (energy)", }, ["ftlbf"] = { name1 = "foot-pound force", name2 = "foot-pounds force", symbol = "ft⋅lbf", utype = "energy", alttype = "torque", scale = 1.3558179483314004, default = "J", link = "Foot-pound (energy)", }, ["ftpdl"] = { name1 = "foot-poundal", symbol = "ft⋅pdl", utype = "energy", scale = 0.0421401100938048, default = "J", }, ["GeV"] = { name1 = "gigaelectronvolt", symbol = "GeV", utype = "energy", scale = 1.602176487e-10, default = "nJ", link = "Electronvolt", }, ["gTNT"] = { name2 = "grams of TNT", symbol = "gram of TNT", usename = 1, utype = "energy", scale = 4184, default = "kJ", link = "TNT equivalent", }, ["Gtoe"] = { name1 = "gigatonne of oil equivalent", name2 = "gigatonnes of oil equivalent", symbol = "Gtoe", utype = "energy", scale = 4.1868e19, default = "EJ", link = "Tonne of oil equivalent", }, ["GtonTNT"] = { name2 = "gigatons of TNT", symbol = "gigaton of TNT", usename = 1, utype = "energy", scale = 4.184e18, default = "EJ", link = "TNT equivalent", }, ["GtTNT"] = { name2 = "gigatonnes of TNT", symbol = "gigatonne of TNT", usename = 1, utype = "energy", scale = 4.184e18, default = "EJ", link = "TNT equivalent", }, ["GW.h"] = { name1 = "gigawatt-hour", symbol = "GW⋅h", utype = "energy", scale = 3.6e12, default = "TJ", link = "Kilowatt-hour", }, ["GWh"] = { name1 = "gigawatt-hour", symbol = "GWh", utype = "energy", scale = 3.6e12, default = "TJ", link = "Kilowatt-hour", }, ["hph"] = { name1 = "horsepower-hour", symbol = "hp⋅h", utype = "energy", scale = 2684519.537696172792, default = "kWh", link = "Horsepower", }, ["inlb"] = { name1 = "inch-pound", symbol = "in⋅lb", utype = "energy", alttype = "torque", scale = 0.1129848290276167, default = "mJ", link = "Foot-pound (energy)", }, ["inlb-f"] = { name1 = "inch-pound force", name2 = "inch-pounds force", symbol = "in⋅lb<sub>f</sub>", utype = "energy", alttype = "torque", scale = 0.1129848290276167, default = "mJ", link = "Foot-pound (energy)", }, ["inlbf"] = { name1 = "inch-pound force", name2 = "inch-pounds force", symbol = "in⋅lbf", utype = "energy", alttype = "torque", scale = 0.1129848290276167, default = "mJ", link = "Foot-pound (energy)", }, ["inoz-f"] = { name1 = "inch-ounce force", name2 = "inch-ounces force", symbol = "in⋅oz<sub>f</sub>", utype = "energy", alttype = "torque", scale = 0.00706155181422604375, default = "mJ", link = "Foot-pound (energy)", }, ["inozf"] = { name1 = "inch-ounce force", name2 = "inch-ounces force", symbol = "in⋅ozf", utype = "energy", alttype = "torque", scale = 0.00706155181422604375, default = "mJ", link = "Foot-pound (energy)", }, ["J"] = { _name1 = "joule", _symbol = "J", utype = "energy", scale = 1, prefixes = 1, default = "cal", link = "Joule", }, ["kBOE"] = { name1 = "kilo barrel of oil equivalent", name2 = "kilo barrels of oil equivalent", symbol = "kBOE", utype = "energy", scale = 6.1178632e12, default = "TJ", link = "Barrel of oil equivalent", }, ["kcal"] = { name1 = "kilocalorie", symbol = "kcal", utype = "energy", scale = 4184, default = "kJ", link = "Calorie", }, ["kcal-15"] = { name1 = "kilocalorie (15°C)", name2 = "kilocalories (15°C)", symbol = "kcal<sub>15</sub>", utype = "energy", scale = 4185.8, default = "kJ", link = "Calorie", }, ["kcal-IT"] = { name1 = "kilocalorie (International Steam Table)", name2 = "kilocalories (International Steam Table)", symbol = "kcal<sub>IT</sub>", utype = "energy", scale = 4186.8, default = "kJ", link = "Calorie", }, ["kcal-th"] = { name1 = "kilocalorie (thermochemical)", name2 = "kilocalories (thermochemical)", symbol = "kcal<sub>th</sub>", utype = "energy", scale = 4184, default = "kJ", link = "Calorie", }, ["kerg"] = { name1 = "kiloerg", symbol = "kerg", utype = "energy", scale = 0.0001, default = "mJ", link = "Erg", }, ["keV"] = { name1 = "kiloelectronvolt", symbol = "keV", utype = "energy", scale = 1.602176487e-16, default = "fJ", link = "Electronvolt", }, ["kgTNT"] = { name2 = "kilograms of TNT", symbol = "kilogram of TNT", usename = 1, utype = "energy", scale = 4184000, default = "MJ", link = "TNT equivalent", }, ["kt(TNT)"] = { name1 = "kilotonne", name1_us = "kiloton", symbol = "kt", utype = "energy", scale = 4.184e12, default = "TJ", link = "TNT equivalent", }, ["ktoe"] = { name1 = "kilotonne of oil equivalent", name2 = "kilotonnes of oil equivalent", symbol = "ktoe", utype = "energy", scale = 4.1868e13, default = "TJ", link = "Tonne of oil equivalent", }, ["ktonTNT"] = { name1 = "kiloton of TNT", name2 = "kilotons of TNT", symbol = "kt", utype = "energy", scale = 4.184e12, default = "TJ", link = "TNT equivalent", }, ["ktTNT"] = { name2 = "kilotonnes of TNT", symbol = "kilotonne of TNT", usename = 1, utype = "energy", scale = 4.184e12, default = "TJ", link = "TNT equivalent", }, ["kW.h"] = { name1 = "kilowatt-hour", symbol = "kW⋅h", utype = "energy", scale = 3600000, default = "MJ", }, ["kWh"] = { name1 = "kilowatt-hour", symbol = "kWh", utype = "energy", scale = 3600000, default = "MJ", }, ["Mcal"] = { name1 = "megacalorie", symbol = "Mcal", utype = "energy", scale = 4184000, default = "MJ", link = "Calorie", }, ["mcal"] = { name1 = "millicalorie", symbol = "mcal", utype = "energy", scale = 0.004184, default = "mJ", link = "Calorie", }, ["Mcal-15"] = { name1 = "megacalorie (15°C)", name2 = "megacalories (15°C)", symbol = "Mcal<sub>15</sub>", utype = "energy", scale = 4185800, default = "MJ", link = "Calorie", }, ["mcal-15"] = { name1 = "millicalorie (15°C)", name2 = "millicalories (15°C)", symbol = "mcal<sub>15</sub>", utype = "energy", scale = 0.0041858, default = "mJ", link = "Calorie", }, ["Mcal-IT"] = { name1 = "megacalorie (International Steam Table)", name2 = "megacalories (International Steam Table)", symbol = "Mcal<sub>IT</sub>", utype = "energy", scale = 4186800, default = "MJ", link = "Calorie", }, ["mcal-IT"] = { name1 = "millicalorie (International Steam Table)", name2 = "millicalories (International Steam Table)", symbol = "mcal<sub>IT</sub>", utype = "energy", scale = 0.0041868, default = "mJ", link = "Calorie", }, ["Mcal-th"] = { name1 = "megacalorie (thermochemical)", name2 = "megacalories (thermochemical)", symbol = "Mcal<sub>th</sub>", utype = "energy", scale = 4184000, default = "MJ", link = "Calorie", }, ["mcal-th"] = { name1 = "millicalorie (thermochemical)", name2 = "millicalories (thermochemical)", symbol = "mcal<sub>th</sub>", utype = "energy", scale = 0.004184, default = "mJ", link = "Calorie", }, ["Merg"] = { name1 = "megaerg", symbol = "Merg", utype = "energy", scale = 0.1, default = "J", link = "Erg", }, ["merg"] = { name1 = "millierg", symbol = "merg", utype = "energy", scale = 0.0000000001, default = "μJ", link = "Erg", }, ["MeV"] = { name1 = "megaelectronvolt", symbol = "MeV", utype = "energy", scale = 1.602176487e-13, default = "pJ", link = "Electronvolt", }, ["meV"] = { name1 = "millielectronvolt", symbol = "meV", utype = "energy", scale = 1.602176487e-22, default = "zJ", link = "Electronvolt", }, ["MMBtu"] = { name1 = "million British thermal units", name2 = "million British thermal units", symbol = "MMBtu", utype = "energy", scale = 1055055852.62, default = "GJ", link = "British thermal unit", }, ["Mt(TNT)"] = { name1 = "megatonne", name1_us = "megaton", symbol = "Mt", utype = "energy", scale = 4.184e15, default = "PJ", link = "TNT equivalent", }, ["Mtoe"] = { name1 = "megatonne of oil equivalent", name2 = "megatonnes of oil equivalent", symbol = "Mtoe", utype = "energy", scale = 4.1868e16, default = "PJ", link = "Tonne of oil equivalent", }, ["MtonTNT"] = { name1 = "megaton of TNT", name2 = "megatons of TNT", symbol = "Mt", utype = "energy", scale = 4.184e15, default = "PJ", link = "TNT equivalent", }, ["mtonTNT"] = { name2 = "millitons of TNT", symbol = "milliton of TNT", usename = 1, utype = "energy", scale = 4184000, default = "MJ", link = "TNT equivalent", }, ["MtTNT"] = { name2 = "megatonnes of TNT", symbol = "megatonne of TNT", usename = 1, utype = "energy", scale = 4.184e15, default = "PJ", link = "TNT equivalent", }, ["mtTNT"] = { name2 = "millitonnes of TNT", symbol = "millitonne of TNT", usename = 1, utype = "energy", scale = 4184000, default = "MJ", link = "TNT equivalent", }, ["MW.h"] = { name1 = "megawatt-hour", symbol = "MW⋅h", utype = "energy", scale = 3600000000, default = "GJ", link = "Kilowatt-hour", }, ["mW.h"] = { name1 = "milliwatt-hour", symbol = "mW⋅h", utype = "energy", scale = 3.6, default = "J", link = "Kilowatt-hour", }, ["MWh"] = { name1 = "megawatt-hour", symbol = "MWh", utype = "energy", scale = 3600000000, default = "GJ", link = "Kilowatt-hour", }, ["mWh"] = { name1 = "milliwatt-hour", symbol = "mWh", utype = "energy", scale = 3.6, default = "J", link = "Kilowatt-hour", }, ["neV"] = { name1 = "nanoelectronvolt", symbol = "neV", utype = "energy", scale = 1.602176487e-28, default = "yJ", link = "Electronvolt", }, ["PeV"] = { name1 = "petaelectronvolt", symbol = "PeV", utype = "energy", scale = 0.0001602176487, default = "mJ", link = "Electronvolt", }, ["peV"] = { name1 = "picoelectronvolt", symbol = "peV", utype = "energy", scale = 1.602176487e-31, default = "yJ", link = "Electronvolt", }, ["PSh"] = { name1 = "Pferdestärkenstunde", symbol = "PSh", utype = "energy", scale = 2647795.5, default = "kWh", }, ["quad"] = { name1 = "quadrillion British thermal units", name2 = "quadrillion British thermal units", symbol = "quad", utype = "energy", scale = 1.054804e18, default = "EJ", link = "Quad (unit)", }, ["Ry"] = { name1 = "rydberg", symbol = "Ry", utype = "energy", scale = 2.1798741e-18, default = "eV", link = "Rydberg constant", }, ["scf"] = { name1 = "standard cubic foot", name2 = "standard cubic feet", symbol = "scf", utype = "energy", scale = 2869.2044809344, default = "kJ", }, ["scfoot"] = { name1 = "standard cubic foot", name2 = "standard cubic foot", symbol = "scf", utype = "energy", scale = 2869.2044809344, default = "kJ", }, ["t(TNT)"] = { name1 = "tonne", name1_us = "ton", symbol = "t", utype = "energy", scale = 4184000000, default = "GJ", link = "TNT equivalent", }, ["TeV"] = { name1 = "teraelectronvolt", symbol = "TeV", utype = "energy", scale = 1.602176487e-7, default = "μJ", link = "Electronvolt", }, ["th"] = { name1 = "thermie", symbol = "th", utype = "energy", scale = 4186800, default = "MJ", link = "Conversion of units#Energy", }, ["thm-EC"] = { name1 = "therm (EC)", name2 = "therms (EC)", symbol = "thm (EC)", utype = "energy", scale = 105506000, default = "MJ", link = "Therm", }, ["thm-UK"] = { name1 = "therm (UK)", name2 = "therms (UK)", symbol = "thm (UK)", utype = "energy", scale = 105505585.257348, default = "MJ", link = "Therm", }, ["thm-US"] = { name1 = "therm (US)", name1_us = "therm (U.S.)", name2 = "therms (US)", name2_us = "therms (U.S.)", symbol = "thm (US)", sym_us = "thm (U.S.)", utype = "energy", scale = 105480400, default = "MJ", link = "Therm", }, ["toe"] = { name1 = "tonne of oil equivalent", name2 = "tonnes of oil equivalent", symbol = "toe", utype = "energy", scale = 41868000000, default = "GJ", }, ["tonTNT"] = { name2 = "tons of TNT", symbol = "ton of TNT", usename = 1, utype = "energy", scale = 4184000000, default = "GJ", link = "TNT equivalent", }, ["tTNT"] = { name2 = "tonnes of TNT", symbol = "tonne of TNT", usename = 1, utype = "energy", scale = 4184000000, default = "GJ", link = "TNT equivalent", }, ["TtonTNT"] = { name2 = "teratons of TNT", symbol = "teraton of TNT", usename = 1, utype = "energy", scale = 4.184e21, default = "ZJ", link = "TNT equivalent", }, ["TtTNT"] = { name2 = "teratonnes of TNT", symbol = "teratonne of TNT", usename = 1, utype = "energy", scale = 4.184e21, default = "ZJ", link = "TNT equivalent", }, ["TW.h"] = { name1 = "terawatt-hour", symbol = "TW⋅h", utype = "energy", scale = 3.6e15, default = "PJ", link = "Kilowatt-hour", }, ["TWh"] = { name1 = "terawatt-hour", symbol = "TWh", utype = "energy", scale = 3.6e15, default = "PJ", link = "Kilowatt-hour", }, ["W.h"] = { name1 = "watt-hour", symbol = "W⋅h", utype = "energy", scale = 3600, default = "kJ", link = "Kilowatt-hour", }, ["Wh"] = { name1 = "watt-hour", symbol = "Wh", utype = "energy", scale = 3600, default = "kJ", link = "Kilowatt-hour", }, ["μerg"] = { name1 = "microerg", symbol = "μerg", utype = "energy", scale = 1e-13, default = "nJ", link = "Erg", }, ["μeV"] = { name1 = "microelectronvolt", symbol = "μeV", utype = "energy", scale = 1.602176487e-25, default = "yJ", link = "Electronvolt", }, ["μW.h"] = { name1 = "microwatt-hour", symbol = "μW⋅h", utype = "energy", scale = 0.0036, default = "mJ", link = "Kilowatt-hour", }, ["μWh"] = { name1 = "microwatt-hour", symbol = "μWh", utype = "energy", scale = 0.0036, default = "mJ", link = "Kilowatt-hour", }, ["-kW.h"] = { target = "kW.h", link = "Kilowatt hour", }, ["btu"] = { target = "BTU", }, ["Calorie"] = { target = "Cal", }, ["ft.lbf"] = { target = "ftlbf", }, ["ft·lbf"] = { target = "ftlbf", }, ["g-cal-15"] = { target = "cal-15", }, ["g-cal-IT"] = { target = "cal-IT", }, ["g-cal-th"] = { target = "cal-th", }, ["g-kcal-15"] = { target = "kcal-15", }, ["g-kcal-IT"] = { target = "kcal-IT", }, ["g-kcal-th"] = { target = "kcal-th", }, ["g-Mcal-15"] = { target = "Mcal-15", }, ["g-mcal-15"] = { target = "mcal-15", }, ["g-Mcal-IT"] = { target = "Mcal-IT", }, ["g-mcal-IT"] = { target = "mcal-IT", }, ["g-Mcal-th"] = { target = "Mcal-th", }, ["g-mcal-th"] = { target = "mcal-th", }, ["GW-h"] = { target = "GW.h", }, ["GW·h"] = { target = "GW.h", }, ["Hartree"] = { target = "Eh", }, ["hp.h"] = { target = "hph", }, ["in.lb-f"] = { target = "inlb-f", }, ["in.lbf"] = { target = "inlbf", }, ["in.oz-f"] = { target = "inoz-f", }, ["in.ozf"] = { target = "inozf", }, ["kbboe"] = { target = "kBOE", symbol = "kbboe", }, ["kg-cal-15"] = { target = "Cal-15", }, ["kg-cal-IT"] = { target = "Cal-IT", }, ["kg-cal-th"] = { target = "Cal-th", }, ["kW-h"] = { target = "kW.h", }, ["kW·h"] = { target = "kW.h", }, ["MW-h"] = { target = "MW.h", }, ["mW-h"] = { target = "mW.h", }, ["MW·h"] = { target = "MW.h", }, ["TW-h"] = { target = "TW.h", }, ["uerg"] = { target = "μerg", }, ["ueV"] = { target = "μeV", }, ["uW-h"] = { target = "μW.h", }, ["uW.h"] = { target = "μW.h", }, ["uWh"] = { target = "μWh", }, ["W-h"] = { target = "W.h", }, ["eVpar"] = { _name1 = "electronvolt", _symbol = "eV", utype = "energy per chemical amount", scale = 96485.329522144166, prefixes = 1, default = "kcal/mol", link = "Electronvolt", }, ["kcal/mol"] = { per = { "kcal", "mol" }, utype = "energy per chemical amount", default = "kJ/mol", link = "Kilocalorie per mole", }, ["kJ/mol"] = { per = { "kJ", "mol" }, utype = "energy per chemical amount", default = "kcal/mol", link = "Joule per mole", }, ["kWh/100 km"] = { name1 = "kilowatt-hour per 100 kilometres", name1_us = "kilowatt-hour per 100 kilometers", name2 = "kilowatt-hours per 100 kilometres", name2_us = "kilowatt-hours per 100 kilometers", symbol = "kW⋅h/100&nbsp;km", utype = "energy per unit length", scale = 36, default = "MJ/km kWh/mi", link = "Kilowatt-hour", }, ["kWh/100 mi"] = { name1 = "kilowatt-hour per 100 miles", name2 = "kilowatt-hours per 100 miles", symbol = "kW⋅h/100&nbsp;mi", utype = "energy per unit length", scale = 22.3694, default = "mpge", link = "Miles per gallon gasoline equivalent", }, ["MJ/100 km"] = { name1 = "megajoule per 100 kilometres", name1_us = "megajoule per 100 kilometers", name2 = "megajoules per 100 kilometres", name2_us = "megajoules per 100 kilometers", symbol = "MJ/100&nbsp;km", utype = "energy per unit length", scale = 10, default = "BTU/mi", link = "British thermal unit", }, ["mpge"] = { name1 = "mile per gallon gasoline equivalent", name2 = "miles per gallon gasoline equivalent", symbol = "mpg&#8209;e", utype = "energy per unit length", scale = 13e-6, invert = -1, iscomplex= true, default = "kWh/100 mi", link = "Miles per gallon gasoline equivalent", }, ["BTU/mi"] = { per = { "BTU", "mi" }, utype = "energy per unit length", default = "v > 1525 ! M ! k ! J/km", }, ["kJ/km"] = { per = { "kJ", "km" }, utype = "energy per unit length", default = "BTU/mi", }, ["kWh/km"] = { per = { "-kW.h", "km" }, utype = "energy per unit length", default = "MJ/km kWh/mi", }, ["kWh/mi"] = { per = { "-kW.h", "mi" }, utype = "energy per unit length", default = "kWh/km MJ/km", }, ["MJ/km"] = { per = { "MJ", "km" }, utype = "energy per unit length", default = "BTU/mi", }, ["mpg-e"] = { target = "mpge", }, ["BTU/lb"] = { name1 = "British thermal unit per pound", name2 = "British thermal units per pound", symbol = "BTU/lb", utype = "energy per unit mass", scale = 429.92261414790346, default = "kJ/kg", link = "British thermal unit", }, ["cal/g"] = { name1 = "calorie per gram", name2 = "calories per gram", symbol = "cal/g", utype = "energy per unit mass", scale = 4184, default = "J/g", }, ["GJ/kg"] = { name1 = "gigajoule per kilogram", name2 = "gigajoules per kilogram", symbol = "GJ/kg", utype = "energy per unit mass", scale = 1e9, default = "ktTNT/t", link = "Specific energy", }, ["J/g"] = { name1 = "joule per gram", name2 = "joules per gram", symbol = "J/g", utype = "energy per unit mass", scale = 1000, default = "kcal/g", link = "Specific energy", }, ["kcal/g"] = { name1 = "kilocalorie per gram", name2 = "kilocalories per gram", symbol = "kcal/g", utype = "energy per unit mass", scale = 4184000, default = "kJ/g", }, ["kJ/g"] = { name1 = "kilojoule per gram", name2 = "kilojoules per gram", symbol = "kJ/g", utype = "energy per unit mass", scale = 1000000, default = "kcal/g", link = "Specific energy", }, ["kJ/kg"] = { name1 = "kilojoule per kilogram", name2 = "kilojoules per kilogram", symbol = "kJ/kg", utype = "energy per unit mass", scale = 1000, default = "BTU/lb", link = "Specific energy", }, ["ktonTNT/MT"] = { name2 = "kilotons of TNT per metric ton", symbol = "kiloton of TNT per metric ton", usename = 1, utype = "energy per unit mass", scale = 4184000000, default = "GJ/kg", link = "TNT equivalent", }, ["ktTNT/t"] = { name2 = "kilotonnes of TNT per tonne", symbol = "kilotonne of TNT per tonne", usename = 1, utype = "energy per unit mass", scale = 4184000000, default = "GJ/kg", link = "TNT equivalent", }, ["MtonTNT/MT"] = { name2 = "megatons of TNT per metric ton", symbol = "megaton of TNT per metric ton", usename = 1, utype = "energy per unit mass", scale = 4.184e12, default = "TJ/kg", link = "TNT equivalent", }, ["MtTNT/MT"] = { name2 = "megatonnes of TNT per tonne", symbol = "megatonne of TNT per tonne", usename = 1, utype = "energy per unit mass", scale = 4.184e12, default = "TJ/kg", link = "TNT equivalent", }, ["TJ/kg"] = { name1 = "terajoule per kilogram", name2 = "terajoules per kilogram", symbol = "TJ/kg", utype = "energy per unit mass", scale = 1e12, default = "MtTNT/MT", link = "Specific energy", }, ["Cal/g"] = { per = { "Cal", "g" }, utype = "energy per unit mass", default = "kJ/g", }, ["BTU/cuft"] = { per = { "BTU", "cuft" }, utype = "energy per unit volume", default = "kJ/L", }, ["Cal/12USoz(mL)serve"] = { per = { "Cal", "-12USoz(mL)serve" }, utype = "energy per unit volume", default = "kJ/L", }, ["Cal/12USoz(ml)serve"] = { per = { "Cal", "-12USoz(ml)serve" }, utype = "energy per unit volume", default = "kJ/l", }, ["Cal/12USozserve"] = { per = { "Cal", "-12USozserve" }, utype = "energy per unit volume", default = "kJ/L", }, ["Cal/USoz"] = { per = { "Cal", "USoz" }, utype = "energy per unit volume", default = "kJ/ml", }, ["kJ/L"] = { per = { "kJ", "L" }, utype = "energy per unit volume", default = "BTU/cuft", }, ["kJ/l"] = { per = { "kJ", "l" }, utype = "energy per unit volume", default = "BTU/cuft", }, ["kJ/ml"] = { per = { "kJ", "ml" }, utype = "energy per unit volume", default = "Cal/USoz", }, ["MJ/m3"] = { per = { "MJ", "m3" }, utype = "energy per unit volume", default = "BTU/cuft", }, ["Sv"] = { _name1 = "sievert", _symbol = "Sv", utype = "equivalent radiation dose", scale = 1, prefixes = 1, default = "rem", link = "Sievert", }, ["rem"] = { _name1 = "rem", _symbol = "rem", utype = "equivalent radiation dose", scale = 0.01, prefixes = 1, default = "Sv", link = "Roentgen equivalent man", }, ["g/km"] = { name1 = "gram per kilometre", name1_us = "gram per kilometer", name2 = "grams per kilometre", name2_us = "grams per kilometer", symbol = "g/km", utype = "exhaust emission", scale = 1e-6, default = "oz/mi", link = "Exhaust gas", }, ["g/mi"] = { name1 = "gram per mile", name2 = "grams per mile", symbol = "g/mi", utype = "exhaust emission", scale = 6.2137119223733397e-7, default = "g/km", link = "Exhaust gas", }, ["gCO2/km"] = { name1 = "gram of CO<sub>2</sub> per kilometre", name1_us = "gram of CO<sub>2</sub> per kilometer", name2 = "grams of CO<sub>2</sub> per kilometre", name2_us = "grams of CO<sub>2</sub> per kilometer", symbol = "g(CO<sub>2</sub>)/km", utype = "exhaust emission", scale = 1e-6, default = "ozCO2/mi", link = "Exhaust gas", }, ["gCO2/mi"] = { name1 = "gram of CO<sub>2</sub> per mile", name2 = "grams of CO<sub>2</sub> per mile", symbol = "g(CO<sub>2</sub>)/mi", utype = "exhaust emission", scale = 6.2137119223733397e-7, default = "gCO2/km", link = "Exhaust gas", }, ["kg/km"] = { name1 = "kilogram per kilometre", name1_us = "kilogram per kilometer", name2 = "kilograms per kilometre", name2_us = "kilograms per kilometer", symbol = "kg/km", utype = "exhaust emission", scale = 0.001, default = "lb/mi", link = "Exhaust gas", }, ["kgCO2/km"] = { name1 = "kilogram of CO<sub>2</sub> per kilometre", name1_us = "kilogram of CO<sub>2</sub> per kilometer", name2 = "kilograms of CO<sub>2</sub> per kilometre", name2_us = "kilograms of CO<sub>2</sub> per kilometer", symbol = "kg(CO<sub>2</sub>)/km", utype = "exhaust emission", scale = 0.001, default = "lbCO2/mi", link = "Exhaust gas", }, ["lb/mi"] = { name1 = "pound per mile", name2 = "pounds per mile", symbol = "lb/mi", utype = "exhaust emission", scale = 0.00028184923173665794, default = "kg/km", link = "Exhaust gas", }, ["lbCO2/mi"] = { name1 = "pound of CO<sub>2</sub> per mile", name2 = "pounds of CO<sub>2</sub> per mile", symbol = "lb(CO<sub>2</sub>)/mi", utype = "exhaust emission", scale = 0.00028184923173665794, default = "kgCO2/km", link = "Exhaust gas", }, ["oz/mi"] = { name1 = "ounce per mile", name2 = "ounces per mile", symbol = "oz/mi", utype = "exhaust emission", scale = 1.7615576983541121e-5, default = "g/km", link = "Exhaust gas", }, ["ozCO2/mi"] = { name1 = "ounce of CO<sub>2</sub> per mile", name2 = "ounces of CO<sub>2</sub> per mile", symbol = "oz(CO<sub>2</sub>)/mi", utype = "exhaust emission", scale = 1.7615576983541121e-5, default = "gCO2/km", link = "Exhaust gas", }, ["cuft/a"] = { name1 = "cubic foot per annum", name2 = "cubic feet per annum", symbol = "cu&nbsp;ft/a", utype = "flow", scale = 8.9730672142368242e-10, default = "m3/a", link = "Cubic foot per second", }, ["cuft/d"] = { name1 = "cubic foot per day", name2 = "cubic feet per day", symbol = "cu&nbsp;ft/d", utype = "flow", scale = 3.2774128000000003e-7, default = "m3/d", link = "Cubic foot per second", }, ["cuft/h"] = { name1 = "cubic foot per hour", name2 = "cubic feet per hour", symbol = "cu&nbsp;ft/h", utype = "flow", scale = 7.8657907200000004e-6, default = "m3/h", link = "Cubic foot per second", }, ["cuft/min"] = { name1 = "cubic foot per minute", name2 = "cubic feet per minute", symbol = "cu&nbsp;ft/min", utype = "flow", scale = 0.00047194744319999999, default = "m3/min", }, ["cuft/s"] = { name1 = "cubic foot per second", name2 = "cubic feet per second", symbol = "cu&nbsp;ft/s", utype = "flow", scale = 28316846592e-12, default = "m3/s", }, ["cumi/a"] = { name1 = "cubic mile per annum", name2 = "cubic miles per annum", symbol = "cu&nbsp;mi/a", utype = "flow", scale = 132.08171170940057, default = "km3/a", link = "Cubic foot per second", }, ["cuyd/h"] = { name1 = "cubic yard per hour", name2 = "cubic yards per hour", symbol = "cuyd/h", utype = "flow", scale = 0.00021237634944000001, default = "m3/h", link = "Cubic foot per second", }, ["cuyd/s"] = { name1 = "cubic yard per second", name2 = "cubic yards per second", symbol = "cu&nbsp;yd/s", utype = "flow", scale = 0.76455485798400002, default = "m3/s", }, ["Goilbbl/a"] = { name1 = "billion barrels per year", name2 = "billion barrels per year", symbol = "Gbbl/a", utype = "flow", scale = 5.0380033629933836, default = "v * 1.58987294928 < 10 ! e6 ! e9 ! m3/a", link = "Barrel per day", }, ["impgal/h"] = { name1 = "imperial gallon per hour", name2 = "imperial gallons per hour", symbol = "imp&nbsp;gal/h", utype = "flow", scale = 1.2628027777777779e-6, default = "m3/h", link = "Gallon", }, ["impgal/min"] = { name1 = "imperial gallon per minute", name2 = "imperial gallons per minute", symbol = "imp gal/min", utype = "flow", scale = 7.5768166666666671e-5, default = "m3/s", link = "Gallon", }, ["impgal/s"] = { name1 = "imperial gallon per second", name2 = "imperial gallons per second", symbol = "impgal/s", utype = "flow", scale = 0.00454609, default = "m3/s", link = "Imperial gallons per second", }, ["km3/a"] = { name1 = "cubic kilometre per annum", name1_us = "cubic kilometer per annum", name2 = "cubic kilometres per annum", name2_us = "cubic kilometers per annum", symbol = "km<sup>3</sup>/a", utype = "flow", scale = 31.68808781402895, default = "cumi/a", link = "Cubic metre per second", }, ["km3/d"] = { name1 = "cubic kilometre per day", name1_us = "cubic kilometer per day", name2 = "cubic kilometres per day", name2_us = "cubic kilometers per day", symbol = "km<sup>3</sup>/d", utype = "flow", scale = 11574.074074074075, default = "cuft/d", link = "Cubic metre per second", }, ["koilbbl/a"] = { name1 = "thousand barrels per year", name2 = "thousand barrels per year", symbol = "kbbl/a", utype = "flow", scale = 5.0380033629933841e-6, default = "v * 1.58987294928 < 10 ! ! e3 ! m3/a", link = "Barrel per day", }, ["koilbbl/d"] = { name1 = "thousand barrels per day", name2 = "thousand barrels per day", symbol = "kbbl/d", utype = "flow", scale = 0.0018401307283333335, default = "v * 1.58987294928 < 10 ! ! e3 ! m3/d", link = "Barrel per day", }, ["L/h"] = { name1 = "litre per hour", name1_us = "liter per hour", name2 = "litres per hour", name2_us = "liters per hour", symbol = "L/h", utype = "flow", scale = 2.7777777777777776e-7, default = "impgal/h USgal/h", link = "Cubic metre per second", }, ["L/min"] = { name1 = "litre per minute", name1_us = "liter per minute", name2 = "litres per minute", name2_us = "liters per minute", symbol = "L/min", utype = "flow", scale = 1.6666666666666667e-5, default = "impgal/min USgal/min", link = "Cubic metre per second", }, ["L/s"] = { name1 = "litre per second", name1_us = "liter per second", name2 = "litres per second", name2_us = "liters per second", symbol = "L/s", utype = "flow", scale = 0.001, default = "cuft/s", link = "Cubic metre per second", }, ["m3/a"] = { name1 = "cubic metre per annum", name1_us = "cubic meter per annum", name2 = "cubic metres per annum", name2_us = "cubic meters per annum", symbol = "m<sup>3</sup>/a", utype = "flow", scale = 3.1688087814028947e-8, default = "cuft/a", link = "Cubic metre per second", }, ["m3/d"] = { name1 = "cubic metre per day", name1_us = "cubic meter per day", name2 = "cubic metres per day", name2_us = "cubic meters per day", symbol = "m<sup>3</sup>/d", utype = "flow", scale = 1.1574074074074073e-5, default = "cuft/d", link = "Cubic metre per second", }, ["m3/h"] = { name1 = "cubic metre per hour", name1_us = "cubic meter per hour", name2 = "cubic metres per hour", name2_us = "cubic meters per hour", symbol = "m<sup>3</sup>/h", utype = "flow", scale = 0.00027777777777777778, default = "cuft/h", link = "Cubic metre per second", }, ["m3/min"] = { name1 = "cubic metre per minute", name1_us = "cubic meter per minute", name2 = "cubic metres per minute", name2_us = "cubic meters per minute", symbol = "m<sup>3</sup>/min", utype = "flow", scale = 0.016666666666666666, default = "cuft/min", link = "Cubic metre per second", }, ["m3/s"] = { name1 = "cubic metre per second", name1_us = "cubic meter per second", name2 = "cubic metres per second", name2_us = "cubic meters per second", symbol = "m<sup>3</sup>/s", utype = "flow", scale = 1, default = "cuft/s", }, ["Moilbbl/a"] = { name1 = "million barrels per year", name2 = "million barrels per year", symbol = "Mbbl/a", utype = "flow", scale = 0.0050380033629933837, default = "v * 1.58987294928 < 10 ! e3 ! e6 ! m3/a", link = "Barrel per day", }, ["Moilbbl/d"] = { name1 = "million barrels per day", name2 = "million barrels per day", symbol = "Mbbl/d", utype = "flow", scale = 1.8401307283333335, default = "v * 1.58987294928 < 10 ! e3 ! e6 ! m3/d", link = "Barrel per day", }, ["oilbbl/a"] = { name1 = "barrel per year", name2 = "barrels per year", symbol = "bbl/a", utype = "flow", scale = 5.0380033629933841e-9, default = "m3/a", link = "Barrel per day", }, ["oilbbl/d"] = { name1 = "barrel per day", name2 = "barrels per day", symbol = "bbl/d", utype = "flow", scale = 1.8401307283333336e-6, default = "m3/d", }, ["Toilbbl/a"] = { name1 = "trillion barrels per year", name2 = "trillion barrels per year", symbol = "Tbbl/a", utype = "flow", scale = 5038.0033629933832, default = "v * 1.58987294928 < 10 ! e9 ! e12 ! m3/a", link = "Barrel per day", }, ["U.S.gal/d"] = { name1 = "U.S. gallon per day", name2 = "U.S. gallons per day", symbol = "U.S.&nbsp;gal/d", utype = "flow", scale = 4.3812636388888893e-8, default = "m3/s", customary= 1, }, ["U.S.gal/h"] = { name1 = "gallon per hour", name2 = "gallons per hour", symbol = "gal/h", utype = "flow", scale = 1.0515032733333334e-6, default = "m3/h", link = "Gallon", customary= 2, }, ["U.S.gal/min"] = { name1 = "U.S. gallon per minute", name2 = "U.S. gallons per minute", symbol = "U.S.&nbsp;gal/min", utype = "flow", scale = 6.3090196400000003e-5, default = "m3/s", link = "Gallon", }, ["USgal/a"] = { name1 = "US gallon per year", name2 = "US gallons per year", symbol = "US&nbsp;gal/a", utype = "flow", scale = 1.1995246102365199e-10, default = "m3/s", }, ["USgal/d"] = { name1 = "US gallon per day", name2 = "US gallons per day", symbol = "US&nbsp;gal/d", utype = "flow", scale = 4.3812636388888893e-8, default = "m3/s", }, ["USgal/h"] = { name1 = "gallon per hour", name2 = "gallons per hour", symbol = "gal/h", utype = "flow", scale = 1.0515032733333334e-6, default = "m3/h", link = "Gallon", customary= 1, }, ["USgal/min"] = { name1 = "US gallon per minute", name2 = "US gallons per minute", symbol = "US&nbsp;gal/min", utype = "flow", scale = 6.3090196400000003e-5, default = "m3/s", link = "Gallon", }, ["USgal/s"] = { name1 = "US gallon per second", name1_us = "U.S. gallon per second", name2 = "US gallons per second", name2_us = "U.S. gallons per second", symbol = "USgal/s", utype = "flow", scale = 0.003785411784, default = "m3/s", link = "US gallons per second", }, ["ft3/a"] = { target = "cuft/a", }, ["ft3/d"] = { target = "cuft/d", }, ["ft3/h"] = { target = "cuft/h", }, ["ft3/s"] = { target = "cuft/s", }, ["Gcuft/a"] = { target = "e9cuft/a", }, ["Gcuft/d"] = { target = "e9cuft/d", }, ["kcuft/a"] = { target = "e3cuft/a", }, ["kcuft/d"] = { target = "e3cuft/d", }, ["kcuft/s"] = { target = "e3cuft/s", }, ["Mcuft/a"] = { target = "e6cuft/a", }, ["Mcuft/d"] = { target = "e6cuft/d", }, ["Mcuft/s"] = { target = "e6cuft/s", }, ["m³/s"] = { target = "m3/s", }, ["Tcuft/a"] = { target = "e12cuft/a", }, ["Tcuft/d"] = { target = "e12cuft/d", }, ["u.s.gal/min"] = { target = "U.S.gal/min", }, ["usgal/min"] = { target = "USgal/min", }, ["-LTf"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "LTf", utype = "force", scale = 9964.01641818352, default = "kN", }, ["-STf"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "STf", utype = "force", scale = 8896.443230521, default = "kN", }, ["dyn"] = { name1 = "dyne", symbol = "dyn", utype = "force", scale = 0.00001, default = "gr-f", }, ["g-f"] = { name1 = "gram-force", name2 = "grams-force", symbol = "g<sub>f</sub>", utype = "force", scale = 0.00980665, default = "mN oz-f", link = "Kilogram-force", }, ["gf"] = { name1 = "gram-force", name2 = "grams-force", symbol = "gf", utype = "force", scale = 0.00980665, default = "mN ozf", link = "Kilogram-force", }, ["gr-f"] = { name1 = "grain-force", name2 = "grains-force", symbol = "gr<sub>f</sub>", utype = "force", scale = 0.0006354602307515, default = "μN", link = "Pound (force)", }, ["grf"] = { name1 = "grain-force", name2 = "grains-force", symbol = "grf", utype = "force", scale = 0.0006354602307515, default = "μN", link = "Pound (force)", }, ["kdyn"] = { name1 = "kilodyne", symbol = "kdyn", utype = "force", scale = 0.01, default = "oz-f", link = "Dyne", }, ["kg-f"] = { name1 = "kilogram-force", name2 = "kilograms-force", symbol = "kg<sub>f</sub>", utype = "force", scale = 9.80665, default = "N lb-f", }, ["kgf"] = { name1 = "kilogram-force", name2 = "kilograms-force", symbol = "kgf", utype = "force", scale = 9.80665, default = "N lbf", }, ["kp"] = { name1 = "kilopond", symbol = "kp", utype = "force", scale = 9.80665, default = "N lb-f", link = "Kilogram-force", }, ["L/T-f"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "L/T<sub>f</sub>", utype = "force", scale = 9964.01641818352, default = "kN", }, ["L/Tf"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "L/Tf", utype = "force", scale = 9964.01641818352, default = "kN", }, ["lb-f"] = { name1 = "pound-force", name2 = "pounds-force", symbol = "lb<sub>f</sub>", utype = "force", scale = 4.4482216152605, default = "N", link = "Pound (force)", }, ["lbf"] = { name1 = "pound-force", name2 = "pounds-force", symbol = "lbf", utype = "force", scale = 4.4482216152605, default = "N", link = "Pound (force)", }, ["lb(f)"] = { name1 = "pound", symbol = "lb", utype = "force", scale = 4.4482216152605, default = "N", link = "Pound (force)", }, ["LT-f"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "LT<sub>f</sub>", utype = "force", scale = 9964.01641818352, default = "kN", }, ["LTf"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "LTf", usename = 1, utype = "force", scale = 9964.01641818352, default = "kN", }, ["Mdyn"] = { name1 = "megadyne", symbol = "Mdyn", utype = "force", scale = 10, default = "lb-f", link = "Dyne", }, ["mdyn"] = { name1 = "millidyne", symbol = "mdyn", utype = "force", scale = 0.00000001, default = "gr-f", link = "Dyne", }, ["mg-f"] = { name1 = "milligram-force", name2 = "milligrams-force", symbol = "mg<sub>f</sub>", utype = "force", scale = 0.00000980665, default = "μN gr-f", link = "Kilogram-force", }, ["mgf"] = { name1 = "milligram-force", name2 = "milligrams-force", symbol = "mgf", utype = "force", scale = 0.00000980665, default = "μN grf", link = "Kilogram-force", }, ["Mp"] = { name1 = "megapond", symbol = "Mp", utype = "force", scale = 9806.65, default = "kN LT-f ST-f", link = "Kilogram-force", }, ["mp"] = { name1 = "millipond", symbol = "mp", utype = "force", scale = 0.00000980665, default = "μN gr-f", link = "Kilogram-force", }, ["N"] = { _name1 = "newton", _symbol = "N", utype = "force", scale = 1, prefixes = 1, default = "lb-f", link = "Newton (unit)", }, ["oz-f"] = { name1 = "ounce-force", name2 = "ounces-force", symbol = "oz<sub>f</sub>", utype = "force", scale = 0.2780138203095378125, default = "mN", link = "Pound (force)", }, ["ozf"] = { name1 = "ounce-force", name2 = "ounces-force", symbol = "ozf", utype = "force", scale = 0.2780138203095378125, default = "mN", link = "Pound (force)", }, ["p"] = { name1 = "pond", symbol = "p", utype = "force", scale = 0.00980665, default = "mN oz-f", link = "Kilogram-force", }, ["pdl"] = { name1 = "poundal", symbol = "pdl", utype = "force", scale = 0.138254954376, default = "N", }, ["S/T-f"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "S/T<sub>f</sub>", utype = "force", scale = 8896.443230521, default = "kN", }, ["S/Tf"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "S/Tf", utype = "force", scale = 8896.443230521, default = "kN", }, ["ST-f"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "ST<sub>f</sub>", utype = "force", scale = 8896.443230521, default = "kN", }, ["STf"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "STf", usename = 1, utype = "force", scale = 8896.443230521, default = "kN", }, ["t-f"] = { name1 = "tonne-force", name2 = "tonnes-force", symbol = "t<sub>f</sub>", utype = "force", scale = 9806.65, default = "kN LT-f ST-f", link = "Ton-force#Tonne-force", }, ["tf"] = { name1 = "tonne-force", name2 = "tonnes-force", symbol = "tf", utype = "force", scale = 9806.65, default = "kN LTf STf", link = "Ton-force#Tonne-force", }, ["dyne"] = { target = "dyn", }, ["newtons"] = { target = "N", }, ["poundal"] = { target = "pdl", }, ["tonne-force"] = { target = "tf", }, ["impgal/mi"] = { per = { "@impgal", "mi" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "l/km USgal/mi", }, ["km/L"] = { per = { "km", "L" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "mpgimp mpgus", }, ["km/l"] = { per = { "km", "l" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "mpgimp mpgus", }, ["L/100 km"] = { per = { "L", "100km" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "mpgimp mpgus", symlink = "[[Fuel economy in automobiles#Units of measure|L/100&nbsp;km]]", }, ["l/100 km"] = { per = { "l", "100km" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "mpgimp mpgus", symlink = "[[Fuel economy in automobiles#Units of measure|l/100&nbsp;km]]", }, ["L/km"] = { per = { "L", "km" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "mpgimp mpgus", }, ["l/km"] = { per = { "l", "km" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "mpgimp mpgus", }, ["mi/impqt"] = { per = { "mi", "impqt" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "km/L", }, ["mi/U.S.qt"] = { per = { "mi", "U.S.qt" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "km/L", }, ["mi/USqt"] = { per = { "mi", "USqt" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "km/L", }, ["mi/usqt"] = { per = { "mi", "usqt" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "km/L", }, ["mpgimp"] = { per = { "mi", "@impgal" }, symbol = "mpg<sub>&#8209;imp</sub>", utype = "fuel efficiency", invert = -1, iscomplex= true, default = "L/100 km+mpgus", symlink = "[[Fuel economy in automobiles#Units of measure|mpg]]<sub>&#8209;[[Imperial units|imp]]</sub>", }, ["mpgus"] = { per = { "mi", "+USgal" }, symbol = "mpg<sub>&#8209;US</sub>", utype = "fuel efficiency", invert = -1, iscomplex= true, default = "L/100 km+mpgimp", symlink = "[[Fuel economy in automobiles#Units of measure|mpg]]<sub>&#8209;[[United States customary units|US]]</sub>", }, ["U.S.gal/mi"] = { per = { "*U.S.gal", "mi" }, sp_us = true, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "l/km impgal/mi", }, ["usgal/mi"] = { per = { "+USgal", "mi" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "l/km impgal/mi", }, ["L/100km"] = { target = "L/100 km", }, ["l/100km"] = { target = "l/100 km", }, ["mpg"] = { shouldbe = "Use %{mpgus%} for miles per US gallon or %{mpgimp%} for miles per imperial gallon (not %{mpg%})", }, ["mpgU.S."] = { target = "mpgus", symbol = "mpg<sub>&#8209;U.S.</sub>", sp_us = true, symlink = "[[Fuel economy in automobiles#Units of measure|mpg]]<sub>&#8209;[[United States customary units|U.S.]]</sub>", }, ["mpgu.s."] = { target = "mpgus", symbol = "mpg<sub>&#8209;U.S.</sub>", sp_us = true, symlink = "[[Fuel economy in automobiles#Units of measure|mpg]]<sub>&#8209;[[United States customary units|U.S.]]</sub>", }, ["mpgUS"] = { target = "mpgus", }, ["USgal/mi"] = { target = "usgal/mi", }, ["kPa/m"] = { per = { "kPa", "-m-frac" }, utype = "fracture gradient", default = "psi/ft", }, ["psi/ft"] = { per = { "psi", "-ft-frac" }, utype = "fracture gradient", default = "kPa/m", }, ["cm/km"] = { name1 = "centimetre per kilometre", name1_us = "centimeter per kilometer", name2 = "centimetres per kilometre", name2_us = "centimeters per kilometer", symbol = "cm/km", utype = "gradient", scale = 0.00001, default = "ft/mi", link = "Grade (slope)", }, ["ft/mi"] = { name1 = "foot per mile", name2 = "feet per mile", symbol = "ft/mi", utype = "gradient", scale = 0.00018939393939393939, default = "v < 5.28 ! c ! ! m/km", link = "Grade (slope)", }, ["ft/nmi"] = { name1 = "foot per nautical mile", name2 = "feet per nautical mile", symbol = "ft/nmi", utype = "gradient", scale = 0.00016457883369330455, default = "v < 6.076 ! c ! ! m/km", link = "Grade (slope)", }, ["in/ft"] = { name1 = "inch per foot", name2 = "inches per foot", symbol = "in/ft", utype = "gradient", scale = 0.083333333333333329, default = "mm/m", link = "Grade (slope)", }, ["in/mi"] = { name1 = "inch per mile", name2 = "inches per mile", symbol = "in/mi", utype = "gradient", scale = 1.5782828282828283e-5, default = "v < 0.6336 ! m ! c ! m/km", link = "Grade (slope)", }, ["m/km"] = { name1 = "metre per kilometre", name1_us = "meter per kilometer", name2 = "metres per kilometre", name2_us = "meters per kilometer", symbol = "m/km", utype = "gradient", scale = 0.001, default = "ft/mi", link = "Grade (slope)", }, ["mm/km"] = { name1 = "millimetre per kilometre", name1_us = "millimeter per kilometer", name2 = "millimetres per kilometre", name2_us = "millimeters per kilometer", symbol = "mm/km", utype = "gradient", scale = 0.000001, default = "in/mi", link = "Grade (slope)", }, ["mm/m"] = { name1 = "millimetre per metre", name1_us = "millimeter per meter", name2 = "millimetres per metre", name2_us = "millimeters per meter", symbol = "mm/m", utype = "gradient", scale = 0.001, default = "in/ft", link = "Grade (slope)", }, ["admi"] = { name1 = "admiralty mile", symbol = "nmi&nbsp;(admiralty)", utype = "length", scale = 1853.184, default = "km mi", link = "Nautical mile", }, ["AU"] = { name1 = "astronomical unit", symbol = "AU", utype = "length", scale = 149597870700, default = "km mi", }, ["Brnmi"] = { name1 = "British nautical mile", symbol = "(Brit)&nbsp;nmi", utype = "length", scale = 1853.184, default = "km mi", link = "Nautical mile", }, ["bu"] = { name2 = "bu", symbol = "bu", usename = 1, utype = "length", scale = 0.0030303030303030303, default = "mm", link = "Japanese units of measurement#Length", }, ["ch"] = { name1 = "chain", symbol = "ch", utype = "length", scale = 20.1168, default = "ft m", subdivs = { ["ft"] = { 66, default = "m" }, ["yd"] = { 22, default = "m" } }, link = "Chain (unit)", }, ["chlk"] = { name1 = "[[Chain (unit)|chain]]", symbol = "[[Chain (unit)|ch]]", utype = "length", scale = 20.1168, default = "ft m", link = "", }, ["chain"] = { symbol = "chain", usename = 1, utype = "length", scale = 20.1168, default = "ft m", subdivs = { ["ft"] = { 66, default = "m" }, ["yd"] = { 22, default = "m" } }, link = "Chain (unit)", }, ["chainlk"] = { symbol = "[[Chain (unit)|chain]]", usename = 1, utype = "length", scale = 20.1168, default = "ft m", link = "", }, ["dpcm"] = { name2 = "dot/cm", symbol = "dot/cm", utype = "length", scale = 100, invert = -1, iscomplex= true, default = "dpi", link = "Dots per inch", }, ["dpi"] = { name2 = "DPI", symbol = "DPI", utype = "length", scale = 39.370078740157481, invert = -1, iscomplex= true, default = "pitch", link = "Dots per inch", }, ["fathom"] = { symbol = "fathom", usename = 1, utype = "length", scale = 1.8288, default = "ft m", }, ["foot"] = { name1 = "foot", name2 = "foot", symbol = "ft", utype = "length", scale = 0.3048, default = "m", subdivs = { ["in"] = { 12, default = "m" } }, link = "Foot (unit)", }, ["ft"] = { name1 = "foot", name2 = "feet", symbol = "ft", utype = "length", scale = 0.3048, exception= "integer_more_precision", default = "m", subdivs = { ["in"] = { 12, default = "m" } }, link = "Foot (unit)", }, ["furlong"] = { symbol = "furlong", usename = 1, utype = "length", scale = 201.168, default = "ft m", }, ["Gly"] = { name1 = "gigalight-year", symbol = "Gly", utype = "length", scale = 9.4607304725808e24, default = "Mpc", link = "Light-year#Definitions", }, ["Gpc"] = { name1 = "gigaparsec", symbol = "Gpc", utype = "length", scale = 3.0856775814671916e25, default = "Gly", link = "Parsec#Megaparsecs and gigaparsecs", }, ["hand"] = { name1 = "hand", symbol = "h", utype = "length", builtin = "hand", scale = 0.1016, iscomplex= true, default = "in cm", link = "Hand (unit)", }, ["in"] = { name1 = "inch", name2 = "inches", symbol = "in", utype = "length", scale = 0.0254, exception= "subunit_more_precision", default = "mm", }, ["inabbreviated"] = { name2 = "in", symbol = "in", utype = "length", scale = 0.0254, default = "mm", link = "Inch", }, ["kly"] = { name1 = "kilolight-year", symbol = "kly", utype = "length", scale = 9.4607304725808e18, default = "pc", link = "Light-year#Definitions", }, ["kpc"] = { name1 = "kiloparsec", symbol = "kpc", utype = "length", scale = 3.0856775814671916e19, default = "kly", link = "Parsec#Parsecs and kiloparsecs", }, ["LD"] = { name1 = "lunar distance", symbol = "LD", utype = "length", scale = 384403000, default = "km mi", link = "Lunar distance (astronomy)", }, ["league"] = { symbol = "league", usename = 1, utype = "length", scale = 4828.032, default = "km", link = "League (unit)", }, ["ly"] = { name1 = "light-year", symbol = "ly", utype = "length", scale = 9.4607304725808e15, default = "AU", }, ["m"] = { _name1 = "metre", _name1_us= "meter", _symbol = "m", utype = "length", scale = 1, prefixes = 1, default = "v > 0 and v < 3 ! ftin ! ft", link = "Metre", }, ["mi"] = { name1 = "mile", symbol = "mi", utype = "length", scale = 1609.344, default = "km", subdivs = { ["ch"] = { 80, default = "km" }, ["chlk"] = { 80, default = "km" }, ["chain"] = { 80, default = "km" }, ["chainlk"] = { 80, default = "km" }, ["ft"] = { 5280, default = "km" }, ["furlong"] = { 8, default = "km" }, ["yd"] = { 1760, default = "km" } }, }, ["mil"] = { symbol = "mil", usename = 1, utype = "length", scale = 0.0000254, default = "mm", link = "Thousandth of an inch", }, ["Mly"] = { name1 = "megalight-year", symbol = "Mly", utype = "length", scale = 9.4607304725808e21, default = "kpc", link = "Light-year#Definitions", }, ["Mpc"] = { name1 = "megaparsec", symbol = "Mpc", utype = "length", scale = 3.0856775814671916e22, default = "Mly", link = "Parsec#Megaparsecs and gigaparsecs", }, ["NM"] = { name1 = "nautical mile", symbol = "NM", utype = "length", scale = 1852, default = "km mi", }, ["nmi"] = { name1 = "nautical mile", symbol = "nmi", utype = "length", scale = 1852, default = "km mi", }, ["oldUKnmi"] = { name1 = "nautical mile", symbol = "nmi", utype = "length", scale = 1853.184, default = "km mi", }, ["oldUSnmi"] = { name1 = "nautical mile", symbol = "nmi", utype = "length", scale = 1853.24496, default = "km mi", }, ["pc"] = { name1 = "parsec", symbol = "pc", utype = "length", scale = 3.0856775814671916e16, default = "ly", }, ["perch"] = { name2 = "perches", symbol = "perch", usename = 1, utype = "length", scale = 5.0292, default = "ft m", link = "Rod (unit)", }, ["pitch"] = { name2 = "μm", symbol = "μm", utype = "length", scale = 1e-6, default = "dpi", defkey = "pitch", linkey = "pitch", link = "Dots per inch", }, ["pole"] = { symbol = "pole", usename = 1, utype = "length", scale = 5.0292, default = "ft m", link = "Rod (unit)", }, ["pre1954U.S.nmi"] = { name1 = "(pre-1954&nbsp;U.S.) nautical mile", symbol = "(pre&#8209;1954&nbsp;U.S.) nmi", utype = "length", scale = 1853.24496, default = "km mi", link = "Nautical mile", }, ["pre1954USnmi"] = { name1 = "(pre-1954&nbsp;US) nautical mile", name1_us = "(pre-1954&nbsp;U.S.) nautical mile", symbol = "(pre&#8209;1954&nbsp;US) nmi", sym_us = "(pre&#8209;1954&nbsp;U.S.) nmi", utype = "length", scale = 1853.24496, default = "km mi", link = "Nautical mile", }, ["rd"] = { name1 = "rod", symbol = "rd", utype = "length", scale = 5.0292, default = "ft m", link = "Rod (unit)", }, ["royal cubit"] = { name1 = "royal cubit", symbol = "cu", utype = "length", scale = 0.524, default = "mm", }, ["rtkm"] = { name1 = "route kilometre", name1_us = "route kilometer", symbol = "km", utype = "length", scale = 1000, default = "mi", link = "Kilometre", }, ["rtmi"] = { name1 = "route mile", symbol = "mi", utype = "length", scale = 1609.344, default = "km", link = "Mile", }, ["shaku"] = { name2 = "shaku", symbol = "shaku", usename = 1, utype = "length", scale = 0.30303030303030304, default = "m", link = "Shaku (unit)", }, ["sm"] = { name1 = "smoot", symbol = "sm", utype = "length", scale = 1.70180, default = "m", link = "Smoot (unit)", }, ["smi"] = { name1 = "statute mile", symbol = "mi", utype = "length", scale = 1609.344, default = "km", subdivs = { ["chain"] = { 80, default = "km" } }, }, ["solar radius"] = { name1 = "solar radius", name2 = "solar radii", symbol = "''R''<sub>☉</sub>", utype = "length", scale = 695700e3, default = "km", }, ["sun"] = { name2 = "sun", symbol = "sun", usename = 1, utype = "length", scale = 0.030303030303030304, default = "mm", link = "Japanese units of measurement#Length", }, ["thou"] = { name2 = "thou", symbol = "thou", usename = 1, utype = "length", scale = 0.0000254, default = "mm", link = "Thousandth of an inch", }, ["verst"] = { symbol = "verst", usename = 1, utype = "length", scale = 1066.8, default = "km mi", }, ["yd"] = { name1 = "yard", symbol = "yd", utype = "length", scale = 0.9144, default = "m", subdivs = { ["ft"] = { 3, default = "m" } }, }, ["μin"] = { name1 = "microinch", name2 = "microinches", symbol = "μin", utype = "length", scale = 0.0000000254, default = "nm", link = "SI prefix#Non-metric units", }, ["Å"] = { name1 = "ångström", symbol = "Å", utype = "length", scale = 0.0000000001, default = "in", }, ["Hz"] = { _name1 = "hertz", _name2 = "hertz", _symbol = "Hz", utype = "length", scale = 3.3356409519815204e-9, invert = -1, iscomplex= true, prefixes = 1, default = "m", link = "Hertz", }, ["rpm"] = { name1 = "revolution per minute", name2 = "revolutions per minute", symbol = "rpm", utype = "length", scale = 5.5594015866358675e-11, invert = -1, iscomplex= true, default = "Hz", link = "Revolutions per minute", }, ["-ft-frac"] = { target = "ft", link = "Fracture gradient", }, ["-in-stiff"] = { target = "in", link = "Stiffness", }, ["-m-frac"] = { target = "m", link = "Fracture gradient", }, ["-m-stiff"] = { target = "m", link = "Stiffness", }, ["100km"] = { target = "km", multiplier= 100, }, ["100mi"] = { target = "mi", multiplier= 100, }, ["100miles"] = { target = "mi", symbol = "miles", multiplier= 100, }, ["admiralty nmi"] = { target = "oldUKnmi", }, ["angstrom"] = { target = "Å", }, ["au"] = { target = "AU", symbol = "au", }, ["feet"] = { target = "ft", }, ["hands"] = { target = "hand", }, ["inch"] = { target = "in", }, ["light-year"] = { target = "ly", }, ["meter"] = { target = "m", sp_us = true, }, ["meters"] = { target = "m", sp_us = true, }, ["metre"] = { target = "m", }, ["metres"] = { target = "m", }, ["micrometre"] = { target = "μm", }, ["micron"] = { target = "μm", default = "μin", }, ["mile"] = { target = "mi", }, ["miles"] = { target = "mi", }, ["parsec"] = { target = "pc", }, ["rod"] = { target = "rd", }, ["smoot"] = { target = "sm", }, ["uin"] = { target = "μin", }, ["yard"] = { target = "yd", }, ["yards"] = { target = "yd", }, ["yds"] = { target = "yd", }, ["dtex"] = { name1 = "decitex", name2 = "decitex", symbol = "dtex", utype = "linear density", scale = 1e-7, default = "lb/yd", link = "Units of textile measurement#Units", }, ["kg/cm"] = { name1 = "kilogram per centimetre", name1_us = "kilogram per centimeter", name2 = "kilograms per centimetre", name2_us = "kilograms per centimeter", symbol = "kg/cm", utype = "linear density", scale = 100, default = "lb/yd", link = "Linear density", }, ["kg/m"] = { name1 = "kilogram per metre", name1_us = "kilogram per meter", name2 = "kilograms per metre", name2_us = "kilograms per meter", symbol = "kg/m", utype = "linear density", scale = 1, default = "lb/yd", link = "Linear density", }, ["lb/ft"] = { name1 = "pound per foot", name2 = "pounds per foot", symbol = "lb/ft", utype = "linear density", scale = 1.4881639435695539, default = "kg/m", link = "Linear density", }, ["lb/yd"] = { name1 = "pound per yard", name2 = "pounds per yard", symbol = "lb/yd", utype = "linear density", scale = 0.49605464785651798, default = "kg/m", link = "Linear density", }, ["G"] = { _name1 = "gauss", _name2 = "gauss", _symbol = "G", utype = "magnetic field strength", scale = 0.0001, prefixes = 1, default = "T", link = "Gauss (unit)", }, ["T"] = { _name1 = "tesla", _symbol = "T", utype = "magnetic field strength", scale = 1, prefixes = 1, default = "G", link = "Tesla (unit)", }, ["A/m"] = { name1 = "ampere per metre", name1_us = "ampere per meter", name2 = "amperes per metre", name2_us = "amperes per meter", symbol = "A/m", utype = "magnetizing field", scale = 1, default = "Oe", }, ["kA/m"] = { name1 = "kiloampere per metre", name1_us = "kiloampere per meter", name2 = "kiloamperes per metre", name2_us = "kiloamperes per meter", symbol = "kA/m", utype = "magnetizing field", scale = 1000, default = "kOe", link = "Ampere per metre", }, ["MA/m"] = { name1 = "megaampere per metre", name1_us = "megaampere per meter", name2 = "megaamperes per metre", name2_us = "megaamperes per meter", symbol = "MA/m", utype = "magnetizing field", scale = 1e6, default = "kOe", link = "Ampere per metre", }, ["Oe"] = { _name1 = "oersted", _symbol = "Oe", utype = "magnetizing field", scale = 79.5774715, prefixes = 1, default = "kA/m", link = "Oersted", }, ["-Lcwt"] = { name1 = "hundredweight", name2 = "hundredweight", symbol = "cwt", utype = "mass", scale = 50.80234544, default = "lb", }, ["-Scwt"] = { name1 = "hundredweight", name2 = "hundredweight", symbol = "cwt", utype = "mass", scale = 45.359237, default = "lb", }, ["-ST"] = { name1 = "short ton", symbol = "ST", utype = "mass", scale = 907.18474, default = "t", }, ["carat"] = { symbol = "carat", usename = 1, utype = "mass", scale = 0.0002, default = "g", link = "Carat (mass)", }, ["drachm"] = { name1_us = "dram", symbol = "drachm", usename = 1, utype = "mass", scale = 0.001771845195, default = "g", link = "Dram (unit)", }, ["dram"] = { target = "drachm", }, ["dwt"] = { name1 = "pennyweight", symbol = "dwt", utype = "mass", scale = 0.00155517384, default = "oz g", }, ["DWton"] = { symbol = "deadweight ton", usename = 1, utype = "mass", scale = 1016.0469088, default = "DWtonne", link = "Deadweight tonnage", }, ["DWtonne"] = { symbol = "deadweight tonne", usename = 1, utype = "mass", scale = 1000, default = "DWton", link = "Deadweight tonnage", }, ["g"] = { _name1 = "gram", _symbol = "g", utype = "mass", scale = 0.001, prefixes = 1, default = "oz", link = "Gram", }, ["gr"] = { name1 = "grain", symbol = "gr", utype = "mass", scale = 0.00006479891, default = "g", link = "Grain (unit)", }, ["Gt"] = { name1 = "gigatonne", symbol = "Gt", utype = "mass", scale = 1000000000000, default = "LT ST", link = "Tonne", }, ["impgalh2o"] = { name1 = "imperial gallon of water", name2 = "imperial gallons of water", symbol = "imp&nbsp;gal H<sub>2</sub>O", utype = "mass", scale = 4.5359236999999499, default = "lb kg", link = "Imperial gallon", }, ["kt"] = { name1 = "kilotonne", symbol = "kt", utype = "mass", scale = 1000000, default = "LT ST", link = "Tonne", }, ["lb"] = { name1 = "pound", symbol = "lb", utype = "mass", scale = 0.45359237, exception= "integer_more_precision", default = "kg", subdivs = { ["oz"] = { 16, default = "kg" } }, link = "Pound (mass)", }, ["Lcwt"] = { name1 = "long hundredweight", name2 = "long hundredweight", symbol = "Lcwt", usename = 1, utype = "mass", scale = 50.80234544, default = "lb", subdivs = { ["qtr"] = { 4, default = "kg" }, ["st"] = { 8, default = "kg" } }, link = "Hundredweight", }, ["long cwt"] = { name1 = "long hundredweight", name2 = "long hundredweight", symbol = "long&nbsp;cwt", utype = "mass", scale = 50.80234544, default = "lb kg", subdivs = { ["qtr"] = { 4, default = "kg" } }, link = "Hundredweight", }, ["long qtr"] = { name1 = "long quarter", symbol = "long&nbsp;qtr", utype = "mass", scale = 12.70058636, default = "lb kg", }, ["LT"] = { symbol = "long ton", usename = 1, utype = "mass", scale = 1016.0469088, default = "t", subdivs = { ["Lcwt"] = { 20, default = "t", unit = "-Lcwt" } }, }, ["lt"] = { name1 = "long ton", symbol = "LT", utype = "mass", scale = 1016.0469088, default = "t", subdivs = { ["Lcwt"] = { 20, default = "t", unit = "-Lcwt" } }, }, ["metric ton"] = { symbol = "metric ton", usename = 1, utype = "mass", scale = 1000, default = "long ton", link = "Tonne", }, ["MT"] = { name1 = "metric ton", symbol = "t", utype = "mass", scale = 1000, default = "LT ST", link = "Tonne", }, ["Mt"] = { name1 = "megatonne", symbol = "Mt", utype = "mass", scale = 1000000000, default = "LT ST", link = "Tonne", }, ["oz"] = { name1 = "ounce", symbol = "oz", utype = "mass", scale = 0.028349523125, default = "g", }, ["ozt"] = { name1 = "troy ounce", symbol = "ozt", utype = "mass", scale = 0.0311034768, default = "oz g", }, ["pdr"] = { name1 = "pounder", symbol = "pdr", utype = "mass", scale = 0.45359237, default = "kg", link = "Pound (mass)", }, ["qtr"] = { name1 = "quarter", symbol = "qtr", utype = "mass", scale = 12.70058636, default = "lb kg", subdivs = { ["lb"] = { 28, default = "kg" } }, link = "Long quarter", }, ["Scwt"] = { name1 = "short hundredweight", name2 = "short hundredweight", symbol = "Scwt", usename = 1, utype = "mass", scale = 45.359237, default = "lb", link = "Hundredweight", }, ["short cwt"] = { name1 = "short hundredweight", name2 = "short hundredweight", symbol = "short&nbsp;cwt", utype = "mass", scale = 45.359237, default = "lb kg", link = "Hundredweight", }, ["short qtr"] = { name1 = "short quarter", symbol = "short&nbsp;qtr", utype = "mass", scale = 11.33980925, default = "lb kg", }, ["ST"] = { symbol = "short ton", usename = 1, utype = "mass", scale = 907.18474, default = "t", subdivs = { ["Scwt"] = { 20, default = "t", unit = "-Scwt" } }, }, ["shtn"] = { name1 = "short ton", symbol = "sh&nbsp;tn", utype = "mass", scale = 907.18474, default = "t", }, ["shton"] = { symbol = "ton", usename = 1, utype = "mass", scale = 907.18474, default = "t", }, ["solar mass"] = { name1 = "solar mass", name2 = "solar masses", symbol = "''M''<sub>☉</sub>", utype = "mass", scale = 1.98855e30, default = "kg", }, ["st"] = { name1 = "stone", name2 = "stone", symbol = "st", utype = "mass", scale = 6.35029318, default = "lb kg", subdivs = { ["lb"] = { 14, default = "kg lb" } }, link = "Stone (unit)", }, ["t"] = { name1 = "tonne", name1_us = "metric ton", symbol = "t", utype = "mass", scale = 1000, default = "LT ST", }, ["tonne"] = { name1 = "tonne", name1_us = "metric ton", symbol = "t", utype = "mass", scale = 1000, default = "shton", }, ["troy pound"] = { symbol = "troy pound", usename = 1, utype = "mass", scale = 0.3732417216, default = "lb kg", link = "Troy weight", }, ["usgalh2o"] = { name1 = "US gallon of water", name1_us = "U.S. gallon of water", name2 = "US gallons of water", name2_us = "U.S. gallons of water", symbol = "US&nbsp;gal H<sub>2</sub>O", utype = "mass", scale = 3.7776215836051126, default = "lb kg", link = "United States customary units#Fluid volume", }, ["viss"] = { name2 = "viss", symbol = "viss", utype = "mass", scale = 1.632932532, default = "kg", link = "Myanmar units of measurement#Mass", }, ["billion tonne"] = { target = "e9t", }, ["kilogram"] = { target = "kg", }, ["kilotonne"] = { target = "kt", }, ["lbs"] = { target = "lb", }, ["lbt"] = { target = "troy pound", }, ["lcwt"] = { target = "Lcwt", }, ["long ton"] = { target = "LT", }, ["mcg"] = { target = "μg", }, ["million tonne"] = { target = "e6t", }, ["scwt"] = { target = "Scwt", }, ["short ton"] = { target = "ST", }, ["stone"] = { target = "st", }, ["thousand tonne"] = { target = "e3t", }, ["tonnes"] = { target = "t", }, ["kg/kW"] = { name1 = "kilogram per kilowatt", name2 = "kilograms per kilowatt", symbol = "kg/kW", utype = "mass per unit power", scale = 0.001, default = "lb/hp", link = "Kilowatt", }, ["lb/hp"] = { name1 = "pound per horsepower", name2 = "pounds per horsepower", symbol = "lb/hp", utype = "mass per unit power", scale = 0.00060827738784176115, default = "kg/kW", link = "Horsepower", }, ["kg/h"] = { per = { "kg", "h" }, utype = "mass per unit time", default = "lb/h", }, ["lb/h"] = { per = { "lb", "h" }, utype = "mass per unit time", default = "kg/h", }, ["g-mol/d"] = { name1 = "gram-mole per day", name2 = "gram-moles per day", symbol = "g&#8209;mol/d", utype = "molar rate", scale = 1.1574074074074073e-5, default = "μmol/s", link = "Mole (unit)", }, ["g-mol/h"] = { name1 = "gram-mole per hour", name2 = "gram-moles per hour", symbol = "g&#8209;mol/h", utype = "molar rate", scale = 0.00027777777777777778, default = "mmol/s", link = "Mole (unit)", }, ["g-mol/min"] = { name1 = "gram-mole per minute", name2 = "gram-moles per minute", symbol = "g&#8209;mol/min", utype = "molar rate", scale = 0.016666666666666666, default = "g-mol/s", link = "Mole (unit)", }, ["g-mol/s"] = { name1 = "gram-mole per second", name2 = "gram-moles per second", symbol = "g&#8209;mol/s", utype = "molar rate", scale = 1, default = "lb-mol/min", link = "Mole (unit)", }, ["gmol/d"] = { name1 = "gram-mole per day", name2 = "gram-moles per day", symbol = "gmol/d", utype = "molar rate", scale = 1.1574074074074073e-5, default = "μmol/s", link = "Mole (unit)", }, ["gmol/h"] = { name1 = "gram-mole per hour", name2 = "gram-moles per hour", symbol = "gmol/h", utype = "molar rate", scale = 0.00027777777777777778, default = "mmol/s", link = "Mole (unit)", }, ["gmol/min"] = { name1 = "gram-mole per minute", name2 = "gram-moles per minute", symbol = "gmol/min", utype = "molar rate", scale = 0.016666666666666666, default = "gmol/s", link = "Mole (unit)", }, ["gmol/s"] = { name1 = "gram-mole per second", name2 = "gram-moles per second", symbol = "gmol/s", utype = "molar rate", scale = 1, default = "lbmol/min", link = "Mole (unit)", }, ["kmol/d"] = { name1 = "kilomole per day", name2 = "kilomoles per day", symbol = "kmol/d", utype = "molar rate", scale = 0.011574074074074073, default = "mmol/s", link = "Mole (unit)", }, ["kmol/h"] = { name1 = "kilomole per hour", name2 = "kilomoles per hour", symbol = "kmol/h", utype = "molar rate", scale = 0.27777777777777779, default = "mol/s", link = "Mole (unit)", }, ["kmol/min"] = { name1 = "kilomole per minute", name2 = "kilomoles per minute", symbol = "kmol/min", utype = "molar rate", scale = 16.666666666666668, default = "mol/s", link = "Kilomole (unit)", }, ["kmol/s"] = { name1 = "kilomole per second", name2 = "kilomoles per second", symbol = "kmol/s", utype = "molar rate", scale = 1000, default = "lb-mol/s", link = "Mole (unit)", }, ["lb-mol/d"] = { name1 = "pound-mole per day", name2 = "pound-moles per day", symbol = "lb&#8209;mol/d", utype = "molar rate", scale = 0.0052499116898148141, default = "mmol/s", link = "Pound-mole", }, ["lb-mol/h"] = { name1 = "pound-mole per hour", name2 = "pound-moles per hour", symbol = "lb&#8209;mol/h", utype = "molar rate", scale = 0.12599788055555555, default = "mol/s", link = "Pound-mole", }, ["lb-mol/min"] = { name1 = "pound-mole per minute", name2 = "pound-moles per minute", symbol = "lb&#8209;mol/min", utype = "molar rate", scale = 7.5598728333333334, default = "mol/s", link = "Pound-mole", }, ["lb-mol/s"] = { name1 = "pound-mole per second", name2 = "pound-moles per second", symbol = "lb&#8209;mol/s", utype = "molar rate", scale = 453.59237, default = "kmol/s", link = "Pound-mole", }, ["lbmol/d"] = { name1 = "pound-mole per day", name2 = "pound-moles per day", symbol = "lbmol/d", utype = "molar rate", scale = 0.0052499116898148141, default = "mmol/s", link = "Pound-mole", }, ["lbmol/h"] = { name1 = "pound-mole per hour", name2 = "pound-moles per hour", symbol = "lbmol/h", utype = "molar rate", scale = 0.12599788055555555, default = "mol/s", link = "Pound-mole", }, ["lbmol/min"] = { name1 = "pound-mole per minute", name2 = "pound-moles per minute", symbol = "lbmol/min", utype = "molar rate", scale = 7.5598728333333334, default = "mol/s", link = "Pound-mole", }, ["lbmol/s"] = { name1 = "pound-mole per second", name2 = "pound-moles per second", symbol = "lbmol/s", utype = "molar rate", scale = 453.59237, default = "kmol/s", link = "Pound-mole", }, ["mmol/s"] = { name1 = "millimole per second", name2 = "millimoles per second", symbol = "mmol/s", utype = "molar rate", scale = 0.001, default = "lb-mol/d", link = "Mole (unit)", }, ["mol/d"] = { name1 = "mole per day", name2 = "moles per day", symbol = "mol/d", utype = "molar rate", scale = 1.1574074074074073e-5, default = "μmol/s", link = "Mole (unit)", }, ["mol/h"] = { name1 = "mole per hour", name2 = "moles per hour", symbol = "mol/h", utype = "molar rate", scale = 0.00027777777777777778, default = "mmol/s", link = "Mole (unit)", }, ["mol/min"] = { name1 = "mole per minute", name2 = "moles per minute", symbol = "mol/min", utype = "molar rate", scale = 0.016666666666666666, default = "mol/s", link = "Mole (unit)", }, ["mol/s"] = { name1 = "mole per second", name2 = "moles per second", symbol = "mol/s", utype = "molar rate", scale = 1, default = "lb-mol/min", link = "Mole (unit)", }, ["μmol/s"] = { name1 = "micromole per second", name2 = "micromoles per second", symbol = "μmol/s", utype = "molar rate", scale = 0.000001, default = "lb-mol/d", link = "Mole (unit)", }, ["umol/s"] = { target = "μmol/s", }, ["/acre"] = { name1 = "per acre", name2 = "per acre", symbol = "/acre", utype = "per unit area", scale = 0.00024710538146716532, default = "/ha", link = "Acre", }, ["/ha"] = { name1 = "per hectare", name2 = "per hectare", symbol = "/ha", utype = "per unit area", scale = 100e-6, default = "/acre", link = "Hectare", }, ["/sqcm"] = { name1 = "per square centimetre", name1_us = "per square centimeter", name2 = "per square centimetre", name2_us = "per square centimeter", symbol = "/cm<sup>2</sup>", utype = "per unit area", scale = 1e4, default = "/sqin", link = "Square centimetre", }, ["/sqin"] = { name1 = "per square inch", name2 = "per square inch", symbol = "/in<sup>2</sup>", utype = "per unit area", scale = 1550.0031000062002, default = "/sqcm", link = "Square inch", }, ["/sqkm"] = { name1 = "per square kilometre", name1_us = "per square kilometer", name2 = "per square kilometre", name2_us = "per square kilometer", symbol = "/km<sup>2</sup>", utype = "per unit area", scale = 1e-6, default = "/sqmi", link = "Square kilometre", }, ["/sqmi"] = { name1 = "per square mile", name2 = "per square mile", symbol = "/sq&nbsp;mi", utype = "per unit area", scale = 3.8610215854244582e-7, default = "/sqkm", link = "Square mile", }, ["PD/acre"] = { name1 = "inhabitant per acre", name2 = "inhabitants per acre", symbol = "/acre", utype = "per unit area", scale = 0.00024710538146716532, default = "PD/ha", link = "Acre", }, ["PD/ha"] = { name1 = "inhabitant per hectare", name2 = "inhabitants per hectare", symbol = "/ha", utype = "per unit area", scale = 100e-6, default = "PD/acre", link = "Hectare", }, ["PD/sqkm"] = { name1 = "inhabitant per square kilometre", name1_us = "inhabitant per square kilometer", name2 = "inhabitants per square kilometre", name2_us = "inhabitants per square kilometer", symbol = "/km<sup>2</sup>", utype = "per unit area", scale = 1e-6, default = "PD/sqmi", link = "Square kilometre", }, ["PD/sqmi"] = { name1 = "inhabitant per square mile", name2 = "inhabitants per square mile", symbol = "/sq&nbsp;mi", utype = "per unit area", scale = 3.8610215854244582e-7, default = "PD/sqkm", link = "Square mile", }, ["/cm2"] = { target = "/sqcm", }, ["/in2"] = { target = "/sqin", }, ["/km2"] = { target = "/sqkm", }, ["pd/acre"] = { target = "PD/acre", }, ["pd/ha"] = { target = "PD/ha", }, ["PD/km2"] = { target = "PD/sqkm", }, ["pd/km2"] = { target = "PD/sqkm", }, ["PD/km²"] = { target = "PD/sqkm", }, ["pd/sqkm"] = { target = "PD/sqkm", }, ["pd/sqmi"] = { target = "PD/sqmi", }, ["/l"] = { name1 = "per litre", name1_us = "per liter", name2 = "per litre", name2_us = "per liter", symbol = "/l", utype = "per unit volume", scale = 1000, default = "/usgal", link = "Litre", }, ["/USgal"] = { name1 = "per gallon", name2 = "per gallon", symbol = "/gal", utype = "per unit volume", scale = 264.172052, default = "/l", link = "US gallon", customary= 2, }, ["/usgal"] = { target = "/USgal", }, ["bhp"] = { name1 = "brake horsepower", name2 = "brake horsepower", symbol = "bhp", utype = "power", scale = 745.69987158227022, default = "kW", link = "Horsepower#Brake horsepower", }, ["Cal/d"] = { name1 = "large calorie per day", name2 = "large calories per day", symbol = "Cal/d", utype = "power", scale = 0.048425925925925928, default = "kJ/d", link = "Calorie", }, ["Cal/h"] = { name1 = "large calorie per hour", name2 = "large calories per hour", symbol = "Cal/h", utype = "power", scale = 1.1622222222222223, default = "kJ/h", link = "Calorie", }, ["cal/h"] = { name1 = "calorie per hour", name2 = "calories per hour", symbol = "cal/h", utype = "power", scale = 0.0011622222222222223, default = "W", link = "Calorie", }, ["CV"] = { name1 = "metric horsepower", name2 = "metric horsepower", symbol = "CV", utype = "power", scale = 735.49875, default = "kW", }, ["hk"] = { name1 = "metric horsepower", name2 = "metric horsepower", symbol = "hk", utype = "power", scale = 735.49875, default = "kW", }, ["hp"] = { name1 = "horsepower", name2 = "horsepower", symbol = "hp", utype = "power", scale = 745.69987158227022, default = "kW", }, ["hp-electric"] = { name1 = "electric horsepower", name2 = "electric horsepower", symbol = "hp", utype = "power", scale = 746, default = "kW", link = "Horsepower#Electrical horsepower", }, ["hp-electrical"] = { name1 = "electrical horsepower", name2 = "electrical horsepower", symbol = "hp", utype = "power", scale = 746, default = "kW", link = "Horsepower#Electrical horsepower", }, ["hp-metric"] = { name1 = "metric horsepower", name2 = "metric horsepower", symbol = "hp", utype = "power", scale = 735.49875, default = "kW", }, ["ihp"] = { name1 = "indicated horsepower", name2 = "indicated horsepower", symbol = "ihp", utype = "power", scale = 745.69987158227022, default = "kW", link = "Horsepower#Indicated horsepower", }, ["kcal/h"] = { name1 = "kilocalorie per hour", name2 = "kilocalories per hour", symbol = "kcal/h", utype = "power", scale = 1.1622222222222223, default = "kW", link = "Calorie", }, ["kJ/d"] = { name1 = "kilojoule per day", name2 = "kilojoules per day", symbol = "kJ/d", utype = "power", scale = 0.011574074074074073, default = "Cal/d", link = "Kilojoule", }, ["kJ/h"] = { name1 = "kilojoule per hour", name2 = "kilojoules per hour", symbol = "kJ/h", utype = "power", scale = 0.27777777777777779, default = "W", link = "Kilojoule", }, ["PS"] = { name1 = "metric horsepower", name2 = "metric horsepower", symbol = "PS", utype = "power", scale = 735.49875, default = "kW", }, ["shp"] = { name1 = "shaft horsepower", name2 = "shaft horsepower", symbol = "shp", utype = "power", scale = 745.69987158227022, default = "kW", link = "Horsepower#Shaft horsepower", }, ["W"] = { _name1 = "watt", _symbol = "W", utype = "power", scale = 1, prefixes = 1, default = "hp", link = "Watt", }, ["BTU/h"] = { per = { "BTU", "h" }, utype = "power", default = "W", }, ["Btu/h"] = { per = { "Btu", "h" }, utype = "power", default = "W", }, ["BHP"] = { target = "bhp", }, ["btu/h"] = { target = "BTU/h", }, ["HP"] = { target = "hp", }, ["Hp"] = { target = "hp", }, ["hp-mechanical"] = { target = "hp", }, ["IHP"] = { target = "ihp", }, ["SHP"] = { target = "shp", }, ["whp"] = { target = "hp", }, ["hp/lb"] = { name1 = "horsepower per pound", name2 = "horsepower per pound", symbol = "hp/lb", utype = "power per unit mass", scale = 1643.986806, default = "kW/kg", link = "Power-to-weight ratio", }, ["hp/LT"] = { name1 = "horsepower per long ton", name2 = "horsepower per long ton", symbol = "hp/LT", utype = "power per unit mass", scale = 0.73392268125000004, default = "kW/t", link = "Power-to-weight ratio", }, ["hp/ST"] = { name1 = "horsepower per short ton", name2 = "horsepower per short ton", symbol = "hp/ST", utype = "power per unit mass", scale = 0.821993403, default = "kW/t", link = "Power-to-weight ratio", }, ["hp/t"] = { name1 = "horsepower per tonne", name2 = "horsepower per tonne", symbol = "hp/t", utype = "power per unit mass", scale = 0.74569987158227022, default = "kW/t", link = "Power-to-weight ratio", }, ["kW/kg"] = { name1 = "kilowatt per kilogram", name2 = "kilowatts per kilogram", symbol = "kW/kg", utype = "power per unit mass", scale = 1000, default = "hp/lb", link = "Power-to-weight ratio", }, ["kW/t"] = { name1 = "kilowatt per tonne", name2 = "kilowatts per tonne", symbol = "kW/t", utype = "power per unit mass", scale = 1, default = "PS/t", link = "Power-to-weight ratio", }, ["PS/t"] = { name1 = "metric horsepower per tonne", name2 = "metric horsepower per tonne", symbol = "PS/t", utype = "power per unit mass", scale = 0.73549875, default = "kW/t", link = "Power-to-weight ratio", }, ["shp/lb"] = { name1 = "shaft horsepower per pound", name2 = "shaft horsepower per pound", symbol = "shp/lb", utype = "power per unit mass", scale = 1643.986806, default = "kW/kg", link = "Power-to-weight ratio", }, ["hp/tonne"] = { target = "hp/t", symbol = "hp/tonne", default = "kW/tonne", }, ["kW/tonne"] = { target = "kW/t", symbol = "kW/tonne", }, ["-lb/in2"] = { name1 = "pound per square inch", name2 = "pounds per square inch", symbol = "lb/in<sup>2</sup>", utype = "pressure", scale = 6894.7572931683608, default = "kPa kgf/cm2", }, ["atm"] = { name1 = "standard atmosphere", symbol = "atm", utype = "pressure", scale = 101325, default = "kPa", link = "Atmosphere (unit)", }, ["Ba"] = { name1 = "barye", symbol = "Ba", utype = "pressure", scale = 0.1, default = "Pa", }, ["bar"] = { symbol = "bar", utype = "pressure", scale = 100000, default = "kPa", link = "Bar (unit)", }, ["dbar"] = { name1 = "decibar", symbol = "dbar", utype = "pressure", scale = 10000, default = "kPa", link = "Bar (unit)", }, ["inHg"] = { name1 = "inch of mercury", name2 = "inches of mercury", symbol = "inHg", utype = "pressure", scale = 3386.388640341, default = "kPa", }, ["kBa"] = { name1 = "kilobarye", symbol = "kBa", utype = "pressure", scale = 100, default = "hPa", link = "Barye", }, ["kg-f/cm2"] = { name1 = "kilogram-force per square centimetre", name1_us = "kilogram-force per square centimeter", name2 = "kilograms-force per square centimetre", name2_us = "kilograms-force per square centimeter", symbol = "kg<sub>f</sub>/cm<sup>2</sup>", utype = "pressure", scale = 98066.5, default = "psi", link = "Kilogram-force", }, ["kg/cm2"] = { name1 = "kilogram per square centimetre", name1_us = "kilogram per square centimeter", name2 = "kilograms per square centimetre", name2_us = "kilograms per square centimeter", symbol = "kg/cm<sup>2</sup>", utype = "pressure", scale = 98066.5, default = "psi", link = "Kilogram-force", }, ["kgf/cm2"] = { name1 = "kilogram-force per square centimetre", name1_us = "kilogram-force per square centimeter", name2 = "kilograms-force per square centimetre", name2_us = "kilograms-force per square centimeter", symbol = "kgf/cm<sup>2</sup>", utype = "pressure", scale = 98066.5, default = "psi", link = "Kilogram-force", }, ["ksi"] = { name1 = "kilopound per square inch", name2 = "kilopounds per square inch", symbol = "ksi", utype = "pressure", scale = 6894757.2931683613, default = "MPa", link = "Pound per square inch", }, ["lbf/in2"] = { name1 = "pound-force per square inch", name2 = "pounds-force per square inch", symbol = "lbf/in<sup>2</sup>", utype = "pressure", scale = 6894.7572931683608, default = "kPa kgf/cm2", }, ["mb"] = { name1 = "millibar", symbol = "mb", utype = "pressure", scale = 100, default = "hPa", link = "Bar (unit)", }, ["mbar"] = { name1 = "millibar", symbol = "mbar", utype = "pressure", scale = 100, default = "hPa", link = "Bar (unit)", }, ["mmHg"] = { name1 = "millimetre of mercury", name1_us = "millimeter of mercury", name2 = "millimetres of mercury", name2_us = "millimeters of mercury", symbol = "mmHg", utype = "pressure", scale = 133.322387415, default = "kPa", }, ["Pa"] = { _name1 = "pascal", _symbol = "Pa", utype = "pressure", scale = 1, prefixes = 1, default = "psi", link = "Pascal (unit)", }, ["psf"] = { name1 = "pound per square foot", name2 = "pounds per square foot", symbol = "psf", utype = "pressure", scale = 47.880258980335839, default = "kPa", link = "Pound per square inch", }, ["psi"] = { name1 = "pound per square inch", name2 = "pounds per square inch", symbol = "psi", utype = "pressure", scale = 6894.7572931683608, default = "kPa", }, ["Torr"] = { name1 = "torr", symbol = "Torr", utype = "pressure", scale = 133.32236842105263, default = "kPa", }, ["N/cm2"] = { per = { "N", "cm2" }, utype = "pressure", default = "psi", }, ["N/m2"] = { per = { "N", "m2" }, utype = "pressure", default = "psi", }, ["g/cm2"] = { per = { "g", "cm2" }, utype = "pressure", default = "lb/sqft", multiplier= 9.80665, }, ["g/m2"] = { per = { "g", "m2" }, utype = "pressure", default = "lb/sqft", multiplier= 9.80665, }, ["kg/ha"] = { per = { "kg", "ha" }, utype = "pressure", default = "lb/acre", multiplier= 9.80665, }, ["kg/m2"] = { per = { "kg", "m2" }, utype = "pressure", default = "lb/sqft", multiplier= 9.80665, }, ["lb/1000sqft"] = { per = { "lb", "1000sqft" }, utype = "pressure", default = "g/m2", multiplier= 9.80665, }, ["lb/acre"] = { per = { "lb", "acre" }, utype = "pressure", default = "kg/ha", multiplier= 9.80665, }, ["lb/sqft"] = { per = { "lb", "sqft" }, utype = "pressure", default = "kg/m2", multiplier= 9.80665, }, ["lb/sqyd"] = { per = { "lb", "sqyd" }, utype = "pressure", default = "kg/m2", multiplier= 9.80665, }, ["LT/acre"] = { per = { "LT", "acre" }, utype = "pressure", default = "t/ha", multiplier= 9.80665, }, ["MT/ha"] = { per = { "MT", "ha" }, utype = "pressure", default = "LT/acre ST/acre", multiplier= 9.80665, }, ["oz/sqft"] = { per = { "oz", "sqft" }, utype = "pressure", default = "g/m2", multiplier= 9.80665, }, ["oz/sqyd"] = { per = { "oz", "sqyd" }, utype = "pressure", default = "g/m2", multiplier= 9.80665, }, ["ST/acre"] = { per = { "ST", "acre" }, utype = "pressure", default = "t/ha", multiplier= 9.80665, }, ["t/ha"] = { per = { "t", "ha" }, utype = "pressure", default = "LT/acre ST/acre", multiplier= 9.80665, }, ["tonne/acre"] = { per = { "tonne", "acre" }, utype = "pressure", default = "tonne/ha", multiplier= 9.80665, }, ["tonne/ha"] = { per = { "tonne", "ha" }, utype = "pressure", default = "tonne/acre", multiplier= 9.80665, }, ["kgfpsqcm"] = { target = "kgf/cm2", }, ["kgpsqcm"] = { target = "kg/cm2", }, ["kN/m2"] = { target = "kPa", }, ["lb/in2"] = { target = "lbf/in2", }, ["torr"] = { target = "Torr", }, ["Bq"] = { _name1 = "becquerel", _symbol = "Bq", utype = "radioactivity", scale = 1, prefixes = 1, default = "pCi", link = "Becquerel", }, ["Ci"] = { _name1 = "curie", _symbol = "Ci", utype = "radioactivity", scale = 3.7e10, prefixes = 1, default = "GBq", link = "Curie (unit)", }, ["Rd"] = { _name1 = "rutherford", _symbol = "Rd", utype = "radioactivity", scale = 1e6, prefixes = 1, default = "MBq", link = "Rutherford (unit)", }, ["cm/h"] = { name1 = "centimetre per hour", name1_us = "centimeter per hour", name2 = "centimetres per hour", name2_us = "centimeters per hour", symbol = "cm/h", utype = "speed", scale = 2.7777777777777775e-6, default = "in/h", link = "Metre per second", }, ["cm/s"] = { name1 = "centimetre per second", name1_us = "centimeter per second", name2 = "centimetres per second", name2_us = "centimeters per second", symbol = "cm/s", utype = "speed", scale = 0.01, default = "in/s", link = "Metre per second", }, ["cm/year"] = { name1 = "centimetre per year", name1_us = "centimeter per year", name2 = "centimetres per year", name2_us = "centimeters per year", symbol = "cm/year", utype = "speed", scale = 3.168873850681143e-10, default = "in/year", link = "Orders of magnitude (speed)", }, ["foot/s"] = { name1 = "foot per second", name2 = "foot per second", symbol = "ft/s", utype = "speed", scale = 0.3048, default = "m/s", }, ["ft/min"] = { name1 = "foot per minute", name2 = "feet per minute", symbol = "ft/min", utype = "speed", scale = 0.00508, default = "m/min", link = "Feet per second", }, ["ft/s"] = { name1 = "foot per second", name2 = "feet per second", symbol = "ft/s", utype = "speed", scale = 0.3048, default = "m/s", link = "Feet per second", }, ["furlong per fortnight"] = { name2 = "furlongs per fortnight", symbol = "furlong per fortnight", usename = 1, utype = "speed", scale = 0.00016630952380952381, default = "km/h mph", link = "FFF system", }, ["in/h"] = { name1 = "inch per hour", name2 = "inches per hour", symbol = "in/h", utype = "speed", scale = 7.0555555555555559e-6, default = "cm/h", link = "Inch", }, ["in/s"] = { name1 = "inch per second", name2 = "inches per second", symbol = "in/s", utype = "speed", scale = 0.0254, default = "cm/s", link = "Inch", }, ["in/year"] = { name1 = "inch per year", name2 = "inches per year", symbol = "in/year", utype = "speed", scale = 8.0489395807301024e-10, default = "cm/year", link = "Orders of magnitude (speed)", }, ["isp"] = { name1 = "second", symbol = "s", utype = "speed", scale = 9.80665, default = "km/s", link = "Specific impulse", }, ["km/d"] = { name1 = "kilometre per day", name1_us = "kilometer per day", name2 = "kilometres per day", name2_us = "kilometers per day", symbol = "km/d", utype = "speed", scale = 1.1574074074074074e-2, default = "mi/d", link = "Orders of magnitude (speed)", }, ["km/h"] = { name1 = "kilometre per hour", name1_us = "kilometer per hour", name2 = "kilometres per hour", name2_us = "kilometers per hour", symbol = "km/h", utype = "speed", scale = 0.27777777777777779, default = "mph", link = "Kilometres per hour", }, ["km/s"] = { name1 = "kilometre per second", name1_us = "kilometer per second", name2 = "kilometres per second", name2_us = "kilometers per second", symbol = "km/s", utype = "speed", scale = 1000, default = "mi/s", link = "Metre per second", }, ["kn"] = { name1 = "knot", symbol = "kn", utype = "speed", scale = 0.51444444444444448, default = "km/h mph", link = "Knot (unit)", }, ["kNs/kg"] = { name2 = "kN&#8209;s/kg", symbol = "kN&#8209;s/kg", utype = "speed", scale = 1000, default = "isp", link = "Specific impulse", }, ["m/min"] = { name1 = "metre per minute", name1_us = "meter per minute", name2 = "metres per minute", name2_us = "meters per minute", symbol = "m/min", utype = "speed", scale = 0.016666666666666666, default = "ft/min", link = "Metre per second", }, ["m/s"] = { name1 = "metre per second", name1_us = "meter per second", name2 = "metres per second", name2_us = "meters per second", symbol = "m/s", utype = "speed", scale = 1, default = "ft/s", }, ["Mach"] = { name2 = "Mach", symbol = "Mach", utype = "speed", builtin = "mach", scale = 0, iscomplex= true, default = "km/h mph", link = "Mach number", }, ["mi/d"] = { name1 = "mile per day", name2 = "miles per day", symbol = "mi/d", utype = "speed", scale = 1.8626666666666667e-2, default = "km/d", link = "Orders of magnitude (speed)", }, ["mi/s"] = { name1 = "mile per second", name2 = "miles per second", symbol = "mi/s", utype = "speed", scale = 1609.344, default = "km/s", link = "Mile", }, ["mm/h"] = { name1 = "millimetre per hour", name1_us = "millimeter per hour", name2 = "millimetres per hour", name2_us = "millimeters per hour", symbol = "mm/h", utype = "speed", scale = 2.7777777777777781e-7, default = "in/h", link = "Metre per second", }, ["mph"] = { name1 = "mile per hour", name2 = "miles per hour", symbol = "mph", utype = "speed", scale = 0.44704, default = "km/h", link = "Miles per hour", }, ["Ns/kg"] = { name2 = "N&#8209;s/kg", symbol = "N&#8209;s/kg", utype = "speed", scale = 1, default = "isp", link = "Specific impulse", }, ["si tsfc"] = { name2 = "g/(kN⋅s)", symbol = "g/(kN⋅s)", utype = "speed", scale = 9.9999628621379242e-7, invert = -1, iscomplex= true, default = "tsfc", link = "Thrust specific fuel consumption", }, ["tsfc"] = { name2 = "lb/(lbf⋅h)", symbol = "lb/(lbf⋅h)", utype = "speed", scale = 2.832545036049801e-5, invert = -1, iscomplex= true, default = "si tsfc", link = "Thrust specific fuel consumption", }, ["cm/y"] = { target = "cm/year", }, ["cm/yr"] = { target = "cm/year", }, ["in/y"] = { target = "in/year", }, ["in/yr"] = { target = "in/year", }, ["knot"] = { target = "kn", }, ["knots"] = { target = "kn", }, ["kph"] = { target = "km/h", }, ["mi/h"] = { target = "mph", }, ["mm/s"] = { per = { "mm", "s" }, utype = "speed", default = "in/s", link = "Metre per second", }, ["C"] = { name1 = "degree Celsius", name2 = "degrees Celsius", symbol = "°C", usesymbol= 1, utype = "temperature", scale = 1, offset = -273.15, iscomplex= true, istemperature= true, default = "F", link = "Celsius", }, ["F"] = { name1 = "degree Fahrenheit", name2 = "degrees Fahrenheit", symbol = "°F", usesymbol= 1, utype = "temperature", scale = 0.55555555555555558, offset = 32-273.15*(9/5), iscomplex= true, istemperature= true, default = "C", link = "Fahrenheit", }, ["K"] = { _name1 = "kelvin", _symbol = "K", usesymbol= 1, utype = "temperature", scale = 1, offset = 0, iscomplex= true, istemperature= true, prefixes = 1, default = "C F", link = "Kelvin", }, ["keVT"] = { name1 = "kiloelectronvolt", symbol = "keV", utype = "temperature", scale = 11.604505e6, offset = 0, iscomplex= true, default = "MK", link = "Electronvolt", }, ["R"] = { name1 = "degree Rankine", name2 = "degrees Rankine", symbol = "°R", usesymbol= 1, utype = "temperature", scale = 0.55555555555555558, offset = 0, iscomplex= true, istemperature= true, default = "K F C", link = "Rankine scale", }, ["Celsius"] = { target = "C", }, ["°C"] = { target = "C", }, ["°F"] = { target = "F", }, ["°R"] = { target = "R", }, ["C-change"] = { name1 = "degree Celsius change", name2 = "degrees Celsius change", symbol = "°C", usesymbol= 1, utype = "temperature change", scale = 1, default = "F-change", link = "Celsius", }, ["F-change"] = { name1 = "degree Fahrenheit change", name2 = "degrees Fahrenheit change", symbol = "°F", usesymbol= 1, utype = "temperature change", scale = 0.55555555555555558, default = "C-change", link = "Fahrenheit", }, ["K-change"] = { name1 = "kelvin change", name2 = "kelvins change", symbol = "K", usesymbol= 1, utype = "temperature change", scale = 1, default = "F-change", link = "Kelvin", }, ["°C-change"] = { target = "C-change", }, ["°F-change"] = { target = "F-change", }, ["century"] = { name1 = "century", name2 = "centuries", symbol = "ha", utype = "time", scale = 3155760000, default = "Gs", }, ["d"] = { name1 = "day", symbol = "d", utype = "time", scale = 86400, default = "ks", }, ["decade"] = { name1 = "decade", symbol = "daa", utype = "time", scale = 315576000, default = "Ms", }, ["dog year"] = { name1 = "dog year", symbol = "dog yr", utype = "time", scale = 220903200, default = "years", link = "List of unusual units of measurement#Dog year", }, ["fortnight"] = { symbol = "fortnight", usename = 1, utype = "time", scale = 1209600, default = "week", }, ["h"] = { name1 = "hour", symbol = "h", utype = "time", scale = 3600, default = "ks", }, ["long billion year"] = { name1 = "billion years", name2 = "billion years", symbol = "Ta", utype = "time", scale = 31557600000000000000, default = "Es", link = "Annum", }, ["millennium"] = { name1 = "millennium", name2 = "millennia", symbol = "ka", utype = "time", scale = 31557600000, default = "Gs", }, ["milliard year"] = { name1 = "milliard years", name2 = "milliard years", symbol = "Ga", utype = "time", scale = 31557600000000000, default = "Ps", link = "Annum", }, ["million year"] = { name1 = "million years", name2 = "million years", symbol = "Ma", utype = "time", scale = 31557600000000, default = "Ts", link = "Annum", }, ["min"] = { name1 = "minute", symbol = "min", utype = "time", scale = 60, default = "s", }, ["month"] = { symbol = "month", usename = 1, utype = "time", scale = 2629800, default = "Ms", }, ["months"] = { name1 = "month", symbol = "mo", utype = "time", scale = 2629800, default = "year", }, ["s"] = { _name1 = "second", _symbol = "s", utype = "time", scale = 1, prefixes = 1, default = "min", link = "Second", }, ["short billion year"] = { name1 = "billion years", name2 = "billion years", symbol = "Ga", utype = "time", scale = 31557600000000000, default = "Ps", link = "Annum", }, ["short trillion year"] = { name1 = "trillion years", name2 = "trillion years", symbol = "Ta", utype = "time", scale = 31557600000000000000, default = "Es", link = "Annum", }, ["thousand million year"] = { name1 = "thousand million years", name2 = "thousand million years", symbol = "Ga", utype = "time", scale = 31557600000000000, default = "Ps", link = "Annum", }, ["wk"] = { symbol = "week", usename = 1, utype = "time", scale = 604800, default = "Ms", }, ["year"] = { name1 = "year", symbol = "a", utype = "time", scale = 31557600, default = "Ms", link = "Annum", }, ["years"] = { name1 = "year", symbol = "yr", utype = "time", scale = 31557600, default = "Ms", link = "Annum", }, ["byr"] = { target = "short billion year", }, ["day"] = { target = "d", }, ["days"] = { target = "d", }, ["dog yr"] = { target = "dog year", }, ["Gyr"] = { target = "thousand million year", }, ["hour"] = { target = "h", }, ["hours"] = { target = "h", }, ["kMyr"] = { target = "thousand million year", }, ["kmyr"] = { target = "thousand million year", }, ["kyr"] = { target = "millennium", }, ["long byr"] = { target = "long billion year", }, ["minute"] = { target = "min", }, ["minutes"] = { target = "min", }, ["mth"] = { target = "month", }, ["Myr"] = { target = "million year", }, ["myr"] = { target = "million year", }, ["second"] = { target = "s", }, ["seconds"] = { target = "s", }, ["tmyr"] = { target = "thousand million year", }, ["tryr"] = { target = "short trillion year", }, ["tyr"] = { target = "millennium", }, ["week"] = { target = "wk", }, ["weeks"] = { target = "wk", }, ["yr"] = { target = "year", }, ["kg.m"] = { name1 = "kilogram metre", name1_us = "kilogram meter", symbol = "kg⋅m", utype = "torque", scale = 9.80665, default = "Nm lbft", link = "Kilogram metre (torque)", }, ["kgf.m"] = { name1 = "kilogram force-metre", name1_us = "kilogram force-meter", symbol = "kgf⋅m", utype = "torque", scale = 9.80665, default = "Nm lbfft", link = "Kilogram metre (torque)", }, ["kgm"] = { name1 = "kilogram metre", name1_us = "kilogram meter", symbol = "kg⋅m", utype = "torque", scale = 9.80665, default = "Nm lbfft", link = "Kilogram metre (torque)", }, ["kpm"] = { name1 = "kilopond metre", name1_us = "kilopond meter", symbol = "kp⋅m", utype = "torque", scale = 9.80665, default = "Nm lbft", link = "Kilogram metre (torque)", }, ["lb-fft"] = { name1 = "pound force-foot", name2 = "pound force-feet", symbol = "ft⋅lb<sub>f</sub>", utype = "torque", scale = 1.3558179483314004, default = "Nm", link = "Pound-foot (torque)", }, ["lb.ft"] = { name1 = "pound force-foot", name2 = "pound force-feet", symbol = "lb⋅ft", utype = "torque", scale = 1.3558179483314004, default = "Nm", link = "Pound-foot (torque)", }, ["lb.in"] = { name1 = "pound force-inch", symbol = "lb⋅in", utype = "torque", scale = 0.1129848290276167, default = "mN.m", link = "Pound-foot (torque)", }, ["lbfft"] = { name1 = "pound force-foot", name2 = "pound force-feet", symbol = "lbf⋅ft", utype = "torque", scale = 1.3558179483314004, default = "Nm", link = "Pound-foot (torque)", }, ["lbft"] = { name1 = "pound-foot", name2 = "pound-feet", symbol = "lb⋅ft", utype = "torque", scale = 1.3558179483314004, default = "Nm", link = "Pound-foot (torque)", }, ["m.kg-f"] = { name1 = "metre kilogram-force", name1_us = "meter kilogram-force", name2 = "metre kilograms-force", name2_us = "meter kilograms-force", symbol = "m⋅kg<sub>f</sub>", utype = "torque", scale = 9.80665, default = "Nm lbfft", link = "Kilogram metre (torque)", }, ["m.kgf"] = { name1 = "metre kilogram-force", name1_us = "meter kilogram-force", name2 = "metre kilograms-force", name2_us = "meter kilograms-force", symbol = "m⋅kgf", utype = "torque", scale = 9.80665, default = "Nm lbfft", link = "Kilogram metre (torque)", }, ["mN.m"] = { name1 = "millinewton-metre", name1_us = "millinewton-meter", symbol = "mN⋅m", utype = "torque", scale = 0.001, default = "lb.in", link = "Newton-metre", }, ["Nm"] = { _name1 = "newton-metre", _name1_us= "newton-meter", _symbol = "N⋅m", utype = "torque", alttype = "energy", scale = 1, prefixes = 1, default = "lbfft", link = "Newton-metre", }, ["kN/m"] = { per = { "kN", "-m-stiff" }, utype = "torque", default = "lbf/in", }, ["lbf/in"] = { per = { "lbf", "-in-stiff" }, utype = "torque", default = "kN/m", }, ["lb-f.ft"] = { target = "lb-fft", }, ["lbf.ft"] = { target = "lbfft", }, ["lbf·ft"] = { target = "lbfft", }, ["lb·ft"] = { target = "lb.ft", }, ["mkg-f"] = { target = "m.kg-f", }, ["mkgf"] = { target = "m.kgf", }, ["N.m"] = { target = "Nm", }, ["N·m"] = { target = "Nm", }, ["ton-mile"] = { symbol = "ton-mile", usename = 1, utype = "transportation", scale = 1.4599723182105602, default = "tkm", }, ["tkm"] = { name1 = "tonne-kilometre", name1_us = "tonne-kilometer", symbol = "tkm", utype = "transportation", scale = 1, default = "ton-mile", }, ["-12USoz(mL)serve"] = { name1_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz (355&nbsp;mL) serving", symbol = "12&nbsp;US&nbsp;fl&nbsp;oz (355&nbsp;mL) serving", sym_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz (355&nbsp;mL) serving", utype = "volume", scale = 0.00035488235475000004, default = "mL", link = "Beverage can#Standard sizes", }, ["-12USoz(ml)serve"] = { name1_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz (355&nbsp;ml) serving", symbol = "12&nbsp;US&nbsp;fl&nbsp;oz (355&nbsp;ml) serving", sym_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz (355&nbsp;ml) serving", utype = "volume", scale = 0.00035488235475000004, default = "ml", link = "Beverage can#Standard sizes", }, ["-12USozserve"] = { name1_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz serving", symbol = "12&nbsp;US&nbsp;fl&nbsp;oz serving", sym_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz serving", utype = "volume", scale = 0.00035488235475000004, default = "mL", link = "Beverage can#Standard sizes", }, ["acre-foot"] = { name1 = "acre-foot", name2 = "acre-foot", symbol = "acre⋅ft", utype = "volume", scale = 1233.48183754752, default = "m3", }, ["acre-ft"] = { name1 = "acre-foot", name2 = "acre-feet", symbol = "acre⋅ft", utype = "volume", scale = 1233.48183754752, default = "m3", }, ["AUtbsp"] = { name1 = "Australian tablespoon", symbol = "AU&nbsp;tbsp", utype = "volume", scale = 0.000020, default = "ml", }, ["Bcuft"] = { name1 = "billion cubic foot", name2 = "billion cubic feet", symbol = "billion cu&nbsp;ft", utype = "volume", scale = 28316846.592, default = "Gl", link = "Cubic foot", }, ["bdft"] = { name1 = "board foot", name2 = "board feet", symbol = "bd&nbsp;ft", utype = "volume", scale = 0.0023597372167, default = "m3", }, ["board feet"] = { name2 = "board feet", symbol = "board foot", usename = 1, utype = "volume", scale = 0.0023597372167, default = "m3", }, ["board foot"] = { name2 = "board foot", symbol = "board foot", usename = 1, utype = "volume", scale = 0.0023597372167, default = "m3", }, ["cc"] = { name1 = "cubic centimetre", name1_us = "cubic centimeter", symbol = "cc", utype = "volume", scale = 0.000001, default = "cuin", }, ["CID"] = { name1 = "cubic inch", name2 = "cubic inches", symbol = "cu&nbsp;in", utype = "volume", scale = 0.000016387064, default = "cc", link = "Cubic inch#Engine displacement", }, ["cord"] = { symbol = "cord", utype = "volume", scale = 3.624556363776, default = "m3", link = "Cord (unit)", }, ["cufoot"] = { name1 = "cubic foot", name2 = "cubic foot", symbol = "cu&nbsp;ft", utype = "volume", scale = 0.028316846592, default = "m3", }, ["cuft"] = { name1 = "cubic foot", name2 = "cubic feet", symbol = "cu&nbsp;ft", utype = "volume", scale = 0.028316846592, default = "m3", }, ["cuin"] = { name1 = "cubic inch", name2 = "cubic inches", symbol = "cu&nbsp;in", utype = "volume", scale = 0.000016387064, default = "cm3", }, ["cumi"] = { name1 = "cubic mile", symbol = "cu&nbsp;mi", utype = "volume", scale = 4168181825.440579584, default = "km3", }, ["cuyd"] = { name1 = "cubic yard", symbol = "cu&nbsp;yd", utype = "volume", scale = 0.764554857984, default = "m3", }, ["firkin"] = { symbol = "firkin", usename = 1, utype = "volume", scale = 0.04091481, default = "l impgal USgal", link = "Firkin (unit)", }, ["foot3"] = { target = "cufoot", }, ["Goilbbl"] = { name1 = "billion barrels", name2 = "billion barrels", symbol = "Gbbl", utype = "volume", scale = 158987294.928, default = "v * 1.58987294928 < 10 ! e6 ! e9 ! m3", link = "Barrel (unit)#Oil barrel", }, ["gr water"] = { name1 = "grains water", name2 = "grains water", symbol = "gr H<sub>2</sub>O", utype = "volume", scale = 0.00000006479891, default = "cm3", link = "Grain (unit)", }, ["grt"] = { name1 = "gross register ton", symbol = "grt", utype = "volume", scale = 2.8316846592, default = "m3", link = "Gross register tonnage", }, ["impbbl"] = { name1 = "imperial barrel", symbol = "imp&nbsp;bbl", utype = "volume", scale = 0.16365924, default = "l impgal USgal", link = "Barrel (unit)", }, ["impbsh"] = { name1 = "imperial bushel", symbol = "imp&nbsp;bsh", utype = "volume", scale = 0.03636872, default = "l impgal USdrygal", }, ["impbu"] = { name1 = "imperial bushel", symbol = "imp&nbsp;bu", utype = "volume", scale = 0.03636872, default = "m3", }, ["impgal"] = { name1 = "imperial gallon", symbol = "imp&nbsp;gal", utype = "volume", scale = 0.00454609, default = "l USgal", }, ["impgi"] = { name1 = "gill", symbol = "gi", utype = "volume", scale = 0.0001420653125, default = "ml USoz", link = "Gill (unit)", }, ["impkenning"] = { name1 = "imperial kenning", symbol = "kenning", utype = "volume", scale = 0.01818436, default = "l USdrygal", link = "Kenning (unit)", }, ["impoz"] = { name1 = "imperial fluid ounce", symbol = "imp&nbsp;fl&nbsp;oz", utype = "volume", scale = 0.0000284130625, default = "ml USoz", }, ["imppk"] = { name1 = "imperial peck", symbol = "pk", utype = "volume", scale = 0.00909218, default = "l USdrygal", link = "Peck", }, ["imppt"] = { name1 = "imperial pint", symbol = "imp&nbsp;pt", utype = "volume", scale = 0.00056826125, default = "l", }, ["impqt"] = { name1 = "imperial quart", symbol = "imp&nbsp;qt", utype = "volume", scale = 0.0011365225, default = "ml USoz", customary= 3, }, ["kilderkin"] = { symbol = "kilderkin", usename = 1, utype = "volume", scale = 0.08182962, default = "l impgal USgal", }, ["koilbbl"] = { name1 = "thousand barrels", name2 = "thousand barrels", symbol = "kbbl", utype = "volume", scale = 158.987294928, default = "v * 1.58987294928 < 10 ! ! e3 ! m3", link = "Barrel (unit)#Oil barrel", }, ["L"] = { _name1 = "litre", _name1_us= "liter", _symbol = "L", utype = "volume", scale = 0.001, prefixes = 1, default = "impgal USgal", link = "Litre", }, ["l"] = { _name1 = "litre", _name1_us= "liter", _symbol = "l", utype = "volume", scale = 0.001, prefixes = 1, default = "impgal USgal", link = "Litre", }, ["m3"] = { _name1 = "cubic metre", _name1_us= "cubic meter", _symbol = "m<sup>3</sup>", prefix_position= 7, utype = "volume", scale = 1, prefixes = 3, default = "cuft", link = "Cubic metre", }, ["Mbbl"] = { name1 = "thousand barrels", name2 = "thousand barrels", symbol = "Mbbl", utype = "volume", scale = 158.987294928, default = "v * 1.58987294928 < 10 ! e3 ! ! m3", link = "Barrel (unit)#Oil barrel", }, ["MMoilbbl"] = { name1 = "million barrels", name2 = "million barrels", symbol = "MMbbl", utype = "volume", scale = 158987.294928, default = "v * 1.58987294928 < 10 ! e3 ! e6 ! m3", link = "Barrel (unit)#Oil barrel", }, ["Moilbbl"] = { name1 = "million barrels", name2 = "million barrels", symbol = "Mbbl", utype = "volume", scale = 158987.294928, default = "v * 1.58987294928 < 10 ! e3 ! e6 ! m3", link = "Barrel (unit)#Oil barrel", }, ["MTON"] = { name1 = "measurement ton", symbol = "MTON", utype = "volume", scale = 1.13267386368, default = "m3", }, ["MUSgal"] = { name1 = "million US gallons", name1_us = "million U.S. gallons", name2 = "million US gallons", name2_us = "million U.S. gallons", symbol = "million US&nbsp;gal", sym_us = "million U.S.&nbsp;gal", utype = "volume", scale = 3785.411784, default = "Ml", link = "US gallon", }, ["oilbbl"] = { name1 = "barrel", symbol = "bbl", utype = "volume", scale = 0.158987294928, default = "m3", link = "Barrel (unit)#Oil barrel", }, ["stere"] = { symbol = "stere", usename = 1, utype = "volume", scale = 1, default = "cuft", }, ["Toilbbl"] = { name1 = "trillion barrels", name2 = "trillion barrels", symbol = "Tbbl", utype = "volume", scale = 158987294928, default = "v * 1.58987294928 < 10 ! e9 ! e12 ! m3", link = "Barrel (unit)#Oil barrel", }, ["USbbl"] = { name1 = "US barrel", name1_us = "U.S. barrel", symbol = "US&nbsp;bbl", sym_us = "U.S.&nbsp;bbl", utype = "volume", scale = 0.119240471196, default = "l USgal impgal", link = "Barrel (unit)", }, ["USbeerbbl"] = { name1 = "US beer barrel", name1_us = "U.S. beer barrel", symbol = "US&nbsp;bbl", sym_us = "U.S.&nbsp;bbl", utype = "volume", scale = 0.117347765304, default = "l USgal impgal", link = "Barrel (unit)", }, ["USbsh"] = { name1 = "US bushel", name1_us = "U.S. bushel", symbol = "US&nbsp;bsh", sym_us = "U.S.&nbsp;bsh", utype = "volume", scale = 0.03523907016688, default = "l USdrygal impgal", link = "Bushel", }, ["USbu"] = { name1 = "US bushel", name1_us = "U.S. bushel", symbol = "US&nbsp;bu", sym_us = "U.S.&nbsp;bu", utype = "volume", scale = 0.03523907016688, default = "l USdrygal impgal", link = "Bushel", }, ["USdrybbl"] = { name1 = "US dry barrel", name1_us = "U.S. dry barrel", symbol = "US&nbsp;dry&nbsp;bbl", sym_us = "U.S.&nbsp;dry&nbsp;bbl", utype = "volume", scale = 0.11562819898508, default = "m3", link = "Barrel (unit)", }, ["USdrygal"] = { name1 = "US dry gallon", name1_us = "U.S. dry gallon", symbol = "US&nbsp;dry&nbsp;gal", sym_us = "U.S.&nbsp;dry&nbsp;gal", utype = "volume", scale = 0.00440488377086, default = "l", link = "Gallon", }, ["USdrypt"] = { name1 = "US dry pint", name1_us = "U.S. dry pint", symbol = "US&nbsp;dry&nbsp;pt", sym_us = "U.S.&nbsp;dry&nbsp;pt", utype = "volume", scale = 0.0005506104713575, default = "ml", link = "Pint", }, ["USdryqt"] = { name1 = "US dry quart", name1_us = "U.S. dry quart", symbol = "US&nbsp;dry&nbsp;qt", sym_us = "U.S.&nbsp;dry&nbsp;qt", utype = "volume", scale = 0.001101220942715, default = "ml", link = "Quart", }, ["USflgal"] = { name1 = "US gallon", name1_us = "U.S. gallon", symbol = "US fl gal", sym_us = "U.S.&nbsp;fl&nbsp;gal", utype = "volume", scale = 0.003785411784, default = "l impgal", link = "Gallon", }, ["USgal"] = { name1 = "US gallon", name1_us = "U.S. gallon", symbol = "US&nbsp;gal", sym_us = "U.S.&nbsp;gal", utype = "volume", scale = 0.003785411784, default = "l impgal", }, ["USgi"] = { name1 = "gill", symbol = "gi", utype = "volume", scale = 0.0001182941183, default = "ml impoz", link = "Gill (unit)", }, ["USkenning"] = { name1 = "US kenning", name1_us = "U.S. kenning", symbol = "US&nbsp;kenning", sym_us = "U.S.&nbsp;kenning", utype = "volume", scale = 0.01761953508344, default = "l impgal", link = "Kenning (unit)", }, ["USmin"] = { name1 = "US minim", name1_us = "U.S. minim", symbol = "US&nbsp;min", sym_us = "U.S.&nbsp;min", utype = "volume", scale = 0.000000061611519921875, default = "ml", link = "Minim (unit)", }, ["USoz"] = { name1 = "US fluid ounce", name1_us = "U.S. fluid ounce", symbol = "US&nbsp;fl&nbsp;oz", sym_us = "U.S.&nbsp;fl&nbsp;oz", utype = "volume", scale = 0.0000295735295625, default = "ml", }, ["USpk"] = { name1 = "US peck", name1_us = "U.S. peck", symbol = "US&nbsp;pk", sym_us = "U.S.&nbsp;pk", utype = "volume", scale = 0.00880976754172, default = "l impgal", link = "Peck", }, ["USpt"] = { name1 = "US pint", name1_us = "U.S. pint", symbol = "US&nbsp;pt", sym_us = "U.S.&nbsp;pt", utype = "volume", scale = 0.000473176473, default = "l imppt", link = "Pint", }, ["USqt"] = { name1 = "US quart", name1_us = "U.S. quart", symbol = "US&nbsp;qt", sym_us = "U.S.&nbsp;qt", utype = "volume", scale = 0.000946352946, default = "ml", link = "Quart", customary= 1, }, ["USquart"] = { name1 = "US quart", name1_us = "U.S. quart", symbol = "US&nbsp;qt", sym_us = "U.S.&nbsp;qt", utype = "volume", scale = 0.000946352946, default = "ml impoz", link = "Quart", }, ["UStbsp"] = { name1 = "US tablespoon", name1_us = "U.S. tablespoon", symbol = "US&nbsp;tbsp", sym_us = "U.S.&nbsp;tbsp", utype = "volume", scale = 1.4786764781250001e-5, default = "ml", }, ["winecase"] = { symbol = "case", usename = 1, utype = "volume", scale = 0.009, default = "l", link = "Case (goods)", }, ["*U.S.drygal"] = { target = "USdrygal", sp_us = true, customary= 2, }, ["*U.S.gal"] = { target = "USgal", sp_us = true, default = "L impgal", customary= 2, }, ["+USdrygal"] = { target = "USdrygal", customary= 1, }, ["+usfloz"] = { target = "USoz", link = "Fluid ounce", customary= 1, }, ["+USgal"] = { target = "USgal", customary= 1, }, ["+USoz"] = { target = "USoz", customary= 1, }, ["@impgal"] = { target = "impgal", link = "Gallon", customary= 3, }, ["acre feet"] = { target = "acre-ft", }, ["acre foot"] = { target = "acre-foot", }, ["acre ft"] = { target = "acre-ft", }, ["acre-feet"] = { target = "acre-ft", }, ["acre.foot"] = { target = "acre-foot", }, ["acre.ft"] = { target = "acre-ft", }, ["acre·ft"] = { target = "acre-ft", }, ["bushels"] = { target = "USbsh", }, ["cid"] = { target = "CID", }, ["ft3"] = { target = "cuft", }, ["gal"] = { target = "USgal", }, ["gallon"] = { shouldbe = "Use %{USgal%} for US gallons or %{impgal%} for imperial gallons (not %{gallon%})", }, ["gallons"] = { shouldbe = "Use %{USgal%} for US gallons or %{impgal%} for imperial gallons (not %{gallons%})", }, ["Gcuft"] = { target = "e9cuft", }, ["impfloz"] = { target = "impoz", }, ["Impgal"] = { target = "impgal", }, ["in3"] = { target = "cuin", symbol = "in<sup>3</sup>", }, ["kcuft"] = { target = "e3cuft", }, ["kcum"] = { target = "e3m3", }, ["km³"] = { target = "km3", }, ["liter"] = { target = "L", sp_us = true, }, ["liters"] = { target = "L", sp_us = true, }, ["litre"] = { target = "L", }, ["litres"] = { target = "L", }, ["Mcuft"] = { target = "e6cuft", }, ["Mcum"] = { target = "e6m3", }, ["Mft3"] = { target = "e6cuft", }, ["mi3"] = { target = "cumi", }, ["m³"] = { target = "m3", }, ["Pcuft"] = { target = "e15cuft", }, ["pt"] = { shouldbe = "Use %{USpt%} for US pints or %{imppt%} for imperial pints (not %{pt%})", }, ["qt"] = { shouldbe = "Use %{USqt%} for US quarts or %{impqt%} for imperial quarts (not %{qt%})", }, ["Tcuft"] = { target = "e12cuft", }, ["Tft3"] = { target = "e12cuft", }, ["U.S.bbl"] = { target = "USbbl", sp_us = true, default = "l U.S.gal impgal", }, ["U.S.beerbbl"] = { target = "USbeerbbl", sp_us = true, default = "l U.S.gal impgal", }, ["U.S.bsh"] = { target = "USbsh", sp_us = true, default = "l U.S.drygal impgal", }, ["U.S.bu"] = { target = "USbu", sp_us = true, default = "l U.S.drygal impgal", }, ["U.S.drybbl"] = { target = "USdrybbl", sp_us = true, }, ["U.S.drygal"] = { target = "USdrygal", sp_us = true, }, ["U.S.drypt"] = { target = "USdrypt", sp_us = true, }, ["U.S.dryqt"] = { target = "USdryqt", sp_us = true, }, ["U.S.flgal"] = { target = "USflgal", sp_us = true, }, ["U.S.floz"] = { target = "USoz", sp_us = true, }, ["U.S.gal"] = { target = "USgal", sp_us = true, default = "L impgal", link = "U.S. gallon", }, ["u.s.gal"] = { target = "USgal", sp_us = true, default = "L impgal", link = "U.S. gallon", }, ["U.S.gi"] = { target = "USgi", sp_us = true, }, ["U.S.kenning"] = { target = "USkenning", sp_us = true, }, ["U.S.oz"] = { target = "USoz", sp_us = true, }, ["U.S.pk"] = { target = "USpk", sp_us = true, }, ["U.S.pt"] = { target = "USpt", sp_us = true, }, ["U.S.qt"] = { target = "USqt", sp_us = true, default = "L impqt", customary= 2, }, ["usbbl"] = { target = "USbbl", }, ["usbeerbbl"] = { target = "USbeerbbl", }, ["usbsh"] = { target = "USbsh", }, ["usbu"] = { target = "USbu", }, ["usdrybbl"] = { target = "USdrybbl", }, ["usdrygal"] = { target = "USdrygal", }, ["usdrypt"] = { target = "USdrypt", }, ["usdryqt"] = { target = "USdryqt", }, ["USfloz"] = { target = "USoz", }, ["usfloz"] = { target = "USoz", }, ["USGAL"] = { target = "USgal", }, ["usgal"] = { target = "USgal", }, ["usgi"] = { target = "USgi", }, ["uskenning"] = { target = "USkenning", }, ["usoz"] = { target = "USoz", }, ["uspk"] = { target = "USpk", }, ["uspt"] = { target = "USpt", }, ["usqt"] = { target = "USqt", }, ["yd3"] = { target = "cuyd", }, ["cuft/sqmi"] = { per = { "cuft", "sqmi" }, utype = "volume per unit area", default = "m3/km2", }, ["m3/ha"] = { name1 = "cubic metre per hectare", name1_us = "cubic meter per hectare", name2 = "cubic metres per hectare", name2_us = "cubic meters per hectare", symbol = "m<sup>3</sup>/ha", utype = "volume per unit area", scale = 0.0001, default = "USbu/acre", link = "Hectare", }, ["m3/km2"] = { per = { "m3", "km2" }, utype = "volume per unit area", default = "cuft/sqmi", }, ["U.S.gal/acre"] = { per = { "U.S.gal", "acre" }, utype = "volume per unit area", default = "m3/km2", }, ["USbu/acre"] = { name2 = "US bushels per acre", symbol = "US bushel per acre", usename = 1, utype = "volume per unit area", scale = 8.7077638761350888e-6, default = "m3/ha", link = "Bushel", }, ["USgal/acre"] = { per = { "USgal", "acre" }, utype = "volume per unit area", default = "m3/km2", }, ["cuyd/mi"] = { per = { "cuyd", "mi" }, utype = "volume per unit length", default = "m3/km", }, ["m3/km"] = { per = { "m3", "km" }, utype = "volume per unit length", default = "cuyd/mi", }, ["mich"] = { combination= { "ch", "mi" }, multiple = { 80 }, utype = "length", }, ["michlk"] = { combination= { "chlk", "mi" }, multiple = { 80 }, utype = "length", }, ["michainlk"] = { combination= { "chainlk", "mi" }, multiple = { 80 }, utype = "length", }, ["miyd"] = { combination= { "yd", "mi" }, multiple = { 1760 }, utype = "length", }, ["miydftin"] = { combination= { "in", "ft", "yd", "mi" }, multiple = { 12, 3, 1760 }, utype = "length", }, ["mift"] = { combination= { "ft", "mi" }, multiple = { 5280 }, utype = "length", }, ["ydftin"] = { combination= { "in", "ft", "yd" }, multiple = { 12, 3 }, utype = "length", }, ["ydft"] = { combination= { "ft", "yd" }, multiple = { 3 }, utype = "length", }, ["ftin"] = { combination= { "in", "ft" }, multiple = { 12 }, utype = "length", }, ["footin"] = { combination= { "in", "foot" }, multiple = { 12 }, utype = "length", }, ["handin"] = { combination= { "in", "hand" }, multiple = { 4 }, utype = "length", }, ["lboz"] = { combination= { "oz", "lb" }, multiple = { 16 }, utype = "mass", }, ["stlb"] = { combination= { "lb", "st" }, multiple = { 14 }, utype = "mass", }, ["stlboz"] = { combination= { "oz", "lb", "st" }, multiple = { 16, 14 }, utype = "mass", }, ["st and lb"] = { combination= { "lb", "st" }, multiple = { 14 }, utype = "mass", }, ["GN LTf"] = { combination= { "GN", "-LTf" }, utype = "force", }, ["GN LTf STf"] = { combination= { "GN", "-LTf", "-STf" }, utype = "force", }, ["GN STf"] = { combination= { "GN", "-STf" }, utype = "force", }, ["GN STf LTf"] = { combination= { "GN", "-STf", "-LTf" }, utype = "force", }, ["kN LTf"] = { combination= { "kN", "-LTf" }, utype = "force", }, ["kN LTf STf"] = { combination= { "kN", "-LTf", "-STf" }, utype = "force", }, ["kN STf"] = { combination= { "kN", "-STf" }, utype = "force", }, ["kN STf LTf"] = { combination= { "kN", "-STf", "-LTf" }, utype = "force", }, ["LTf STf"] = { combination= { "-LTf", "-STf" }, utype = "force", }, ["MN LTf"] = { combination= { "MN", "-LTf" }, utype = "force", }, ["MN LTf STf"] = { combination= { "MN", "-LTf", "-STf" }, utype = "force", }, ["MN STf"] = { combination= { "MN", "-STf" }, utype = "force", }, ["MN STf LTf"] = { combination= { "MN", "-STf", "-LTf" }, utype = "force", }, ["STf LTf"] = { combination= { "-STf", "-LTf" }, utype = "force", }, ["L/100 km mpgimp"] = { combination= { "L/100 km", "mpgimp" }, utype = "fuel efficiency", }, ["l/100 km mpgimp"] = { combination= { "l/100 km", "mpgimp" }, utype = "fuel efficiency", }, ["L/100 km mpgUS"] = { combination= { "L/100 km", "mpgus" }, utype = "fuel efficiency", }, ["L/100 km mpgus"] = { combination= { "L/100 km", "mpgus" }, utype = "fuel efficiency", }, ["l/100 km mpgus"] = { combination= { "l/100 km", "mpgus" }, utype = "fuel efficiency", }, ["mpgimp L/100 km"] = { combination= { "mpgimp", "L/100 km" }, utype = "fuel efficiency", }, ["LT ST t"] = { combination= { "lt", "-ST", "t" }, utype = "mass", }, ["LT t ST"] = { combination= { "lt", "t", "-ST" }, utype = "mass", }, ["ST LT t"] = { combination= { "-ST", "lt", "t" }, utype = "mass", }, ["ST t LT"] = { combination= { "-ST", "t", "lt" }, utype = "mass", }, ["t LT ST"] = { combination= { "t", "lt", "-ST" }, utype = "mass", }, ["ton"] = { combination= { "LT", "ST" }, utype = "mass", }, ["kPa kg/cm2"] = { combination= { "kPa", "kgf/cm2" }, utype = "pressure", }, ["kPa lb/in2"] = { combination= { "kPa", "-lb/in2" }, utype = "pressure", }, ["floz"] = { combination= { "impoz", "USoz" }, utype = "volume", }, } --------------------------------------------------------------------------- -- Do not change the data in this table because it is created by running -- -- a script that reads the wikitext from a wiki page (see note above). -- --------------------------------------------------------------------------- local default_exceptions = { -- Prefixed units with a default different from that of the base unit. -- Each key item is a prefixed symbol (unitcode for engineering notation). ["cm<sup>2</sup>"] = "sqin", ["dm<sup>2</sup>"] = "sqin", ["e3acre"] = "km2", ["e3m2"] = "e6sqft", ["e6acre"] = "km2", ["e6ha"] = "e6acre", ["e6km2"] = "e6sqmi", ["e6m2"] = "e6sqft", ["e6sqft"] = "v * 9.290304 < 100 ! e3 ! e6 ! m2", ["e6sqmi"] = "e6km2", ["hm<sup>2</sup>"] = "acre", ["km<sup>2</sup>"] = "sqmi", ["mm<sup>2</sup>"] = "sqin", ["aJ"] = "eV", ["e3BTU"] = "MJ", ["e6BTU"] = "GJ", ["EJ"] = "kWh", ["fJ"] = "keV", ["GJ"] = "kWh", ["MJ"] = "kWh", ["PJ"] = "kWh", ["pJ"] = "MeV", ["TJ"] = "kWh", ["YJ"] = "kWh", ["yJ"] = "μeV", ["ZJ"] = "kWh", ["zJ"] = "meV", ["e12cuft/a"] = "v * 2.8316846592 < 100 ! e9 ! e12 ! m3/a", ["e12cuft/d"] = "v * 2.8316846592 < 100 ! e9 ! e12 ! m3/d", ["e12m3/a"] = "Tcuft/a", ["e12m3/d"] = "Tcuft/d", ["e3cuft/a"] = "v * 2.8316846592 < 100 ! ! e3 ! m3/a", ["e3cuft/d"] = "v * 2.8316846592 < 100 ! ! e3 ! m3/d", ["e3cuft/s"] = "v * 2.8316846592 < 100 ! ! e3 ! m3/s", ["e3m3/a"] = "v < 28.316846592 ! k ! M ! cuft/a", ["e3m3/d"] = "v < 28.316846592 ! k ! M ! cuft/d", ["e3m3/s"] = "v < 28.316846592 ! k ! M ! cuft/s", ["e3USgal/a"] = "v * 3.785411784 < 1000 ! ! e3 ! m3/a", ["e6cuft/a"] = "v * 2.8316846592 < 100 ! e3 ! e6 ! m3/a", ["e6cuft/d"] = "v * 2.8316846592 < 100 ! e3 ! e6 ! m3/d", ["e6cuft/s"] = "v * 2.8316846592 < 100 ! e3 ! e6 ! m3/s", ["e6m3/a"] = "v < 28.316846592 ! M ! G ! cuft/a", ["e6m3/d"] = "v < 28.316846592 ! M ! G ! cuft/d", ["e6m3/s"] = "v < 28.316846592 ! e6 ! e9 ! cuft/s", ["e6USgal/a"] = "v * 3.785411784 < 1000 ! e3 ! e6 ! m3/a", ["e9cuft/a"] = "m3/a", ["e9cuft/d"] = "v * 2.8316846592 < 100 ! e6 ! e9 ! m3/d", ["e9m3/a"] = "v < 28.316846592 ! G ! T ! cuft/a", ["e9m3/d"] = "v < 28.316846592 ! G ! T ! cuft/d", ["e9m3/s"] = "v < 28.316846592 ! e9 ! e12 ! cuft/s", ["e9USgal/a"] = "v * 3.785411784 < 1000 ! e6 ! e9 ! m3/a", ["e9USgal/s"] = "v * 3.785411784 < 1000 ! e6 ! e9 ! m3/s", ["nN"] = "gr-f", ["μN"] = "gr-f", ["mN"] = "oz-f", ["am"] = "in", ["cm"] = "in", ["dam"] = "ft", ["dm"] = "in", ["e12km"] = "e12mi", ["e12mi"] = "e12km", ["e3AU"] = "ly", ["e3km"] = "e3mi", ["e3mi"] = "e3km", ["e6km"] = "e6mi", ["e6mi"] = "e6km", ["e9km"] = "AU", ["e9mi"] = "e9km", ["Em"] = "mi", ["fm"] = "in", ["Gm"] = "mi", ["hm"] = "ft", ["km"] = "mi", ["mm"] = "in", ["Mm"] = "mi", ["nm"] = "in", ["Pm"] = "mi", ["pm"] = "in", ["Tm"] = "mi", ["Ym"] = "mi", ["ym"] = "in", ["Zm"] = "mi", ["zm"] = "in", ["μm"] = "in", ["e12lb"] = "v * 4.5359237 < 10 ! Mt ! Gt", ["e3lb"] = "v * 4.5359237 < 10 ! kg ! t", ["e3ozt"] = "v * 0.311034768 < 10 ! kg ! t", ["e3t"] = "LT ST", ["e6carat"] = "t", ["e6lb"] = "v * 4.5359237 < 10 ! t ! kilotonne", ["e6ozt"] = "lb kg", ["e6ST"] = "Mt", ["e6t"] = "LT ST", ["e9lb"] = "v * 4.5359237 < 10 ! kilotonne ! Mt", ["e9t"] = "LT ST", ["Gg"] = "lb", ["kg"] = "lb", ["mg"] = "gr", ["Mg"] = "LT ST", ["ng"] = "gr", ["μg"] = "gr", ["mBq"] = "fCi", ["kBq"] = "nCi", ["MBq"] = "μCi", ["GBq"] = "mCi", ["TBq"] = "Ci", ["PBq"] = "kCi", ["EBq"] = "kCi", ["fCi"] = "mBq", ["pCi"] = "Bq", ["nCi"] = "Bq", ["μCi"] = "kBq", ["mCi"] = "MBq", ["kCi"] = "TBq", ["MCi"] = "PBq", ["ns"] = "μs", ["μs"] = "ms", ["ms"] = "s", ["ks"] = "h", ["Ms"] = "week", ["Gs"] = "decade", ["Ts"] = "millennium", ["Ps"] = "million year", ["Es"] = "thousand million year", ["MK"] = "keVT", ["cL"] = "impoz usoz", ["cl"] = "impoz usoz", ["cm<sup>3</sup>"] = "cuin", ["dL"] = "impoz usoz", ["dl"] = "impoz usoz", ["mm<sup>3</sup>"] = "cuin", ["dm<sup>3</sup>"] = "cuin", ["e12cuft"] = "v * 2.8316846592 < 100 ! e9 ! e12 ! m3", ["e12impgal"] = "v * 4.54609 < 1000 ! T ! P ! l", ["e12m3"] = "v < 28.316846592 ! T ! P ! cuft", ["e12U.S.gal"] = "v * 3.785411784 < 1000 ! T ! P ! l", ["e12USgal"] = "v * 3.785411784 < 1000 ! T ! P ! l", ["e15cuft"] = "v * 2.8316846592 < 100 ! e12 ! e15 ! m3", ["e15m3"] = "Pcuft", ["e3bdft"] = "v * 0.23597372167 < 100 ! e3 ! e6 ! m3", ["e3cuft"] = "v * 2.8316846592 < 100 ! ! e3 ! m3", ["e3impgal"] = "v * 4.54609 < 1000 ! k ! M ! l", ["e3m3"] = "v < 28.316846592 ! k ! M ! cuft", ["e3U.S.gal"] = "v * 3.785411784 < 1000 ! k ! M ! l", ["e3USgal"] = "v * 3.785411784 < 1000 ! k ! M ! l", ["e6bdft"] = "v * 0.23597372167 < 100 ! e3 ! e6 ! m3", ["e6cuft"] = "v * 2.8316846592 < 100 ! e3 ! e6 ! m3", ["e6cuyd"] = "v * 7.64554857984 < 10 ! e3 ! e6 ! m3", ["e6impgal"] = "v * 4.54609 < 1000 ! M ! G ! l", ["e6L"] = "USgal", ["e6m3"] = "v < 28.316846592 ! M ! G ! cuft", ["e6U.S.gal"] = "v * 3.785411784 < 1000 ! M ! G ! l", ["e6USgal"] = "v * 3.785411784 < 1000 ! M ! G ! l", ["e9bdft"] = "v * 0.23597372167 < 100 ! e6 ! e9 ! m3", ["e9cuft"] = "v * 2.8316846592 < 100 ! e6 ! e9 ! m3", ["e9impgal"] = "v * 4.54609 < 1000 ! G ! T ! l", ["e9m3"] = "v < 28.316846592 ! G ! T ! cuft", ["e9U.S.gal"] = "v * 3.785411784 < 1000 ! G ! T ! l", ["e9USgal"] = "v * 3.785411784 < 1000 ! G ! T ! l", ["GL"] = "cuft", ["Gl"] = "cuft", ["kL"] = "cuft", ["kl"] = "cuft", ["km<sup>3</sup>"] = "cumi", ["mL"] = "impoz usoz", ["ml"] = "impoz usoz", ["Ml"] = "v < 28.316846592 ! e3 ! e6 ! cuft", ["ML"] = "v < 28.316846592 ! e3 ! e6 ! cuft", ["TL"] = "cumi", ["Tl"] = "cumi", ["μL"] = "cuin", ["μl"] = "cuin", } --------------------------------------------------------------------------- -- Do not change the data in this table because it is created by running -- -- a script that reads the wikitext from a wiki page (see note above). -- --------------------------------------------------------------------------- local link_exceptions = { -- Prefixed units with a linked article different from that of the base unit. -- Each key item is a prefixed symbol (not unitcode). ["mm<sup>2</sup>"] = "Square millimetre", ["cm<sup>2</sup>"] = "Square centimetre", ["dm<sup>2</sup>"] = "Square decimetre", ["km<sup>2</sup>"] = "Square kilometre", ["kJ"] = "Kilojoule", ["MJ"] = "Megajoule", ["GJ"] = "Gigajoule", ["TJ"] = "Terajoule", ["fm"] = "Femtometre", ["pm"] = "Picometre", ["nm"] = "Nanometre", ["μm"] = "Micrometre", ["mm"] = "Millimetre", ["cm"] = "Centimetre", ["dm"] = "Decimetre", ["dam"] = "Decametre", ["hm"] = "Hectometre", ["km"] = "Kilometre", ["Mm"] = "Megametre", ["Gm"] = "Gigametre", ["Tm"] = "Terametre", ["Pm"] = "Petametre", ["Em"] = "Exametre", ["Zm"] = "Zettametre", ["Ym"] = "Yottametre", ["μg"] = "Microgram", ["mg"] = "Milligram", ["kg"] = "Kilogram", ["Mg"] = "Tonne", ["yW"] = "Yoctowatt", ["zW"] = "Zeptowatt", ["aW"] = "Attowatt", ["fW"] = "Femtowatt", ["pW"] = "Picowatt", ["nW"] = "Nanowatt", ["μW"] = "Microwatt", ["mW"] = "Milliwatt", ["kW"] = "Kilowatt", ["MW"] = "Megawatt", ["GW"] = "Gigawatt", ["TW"] = "Terawatt", ["PW"] = "Petawatt", ["EW"] = "Exawatt", ["ZW"] = "Zettawatt", ["YW"] = "Yottawatt", ["as"] = "Attosecond", ["fs"] = "Femtosecond", ["ps"] = "Picosecond", ["ns"] = "Nanosecond", ["μs"] = "Microsecond", ["ms"] = "Millisecond", ["ks"] = "Kilosecond", ["Ms"] = "Megasecond", ["Gs"] = "Gigasecond", ["Ts"] = "Terasecond", ["Ps"] = "Petasecond", ["Es"] = "Exasecond", ["Zs"] = "Zettasecond", ["Ys"] = "Yottasecond", ["mm<sup>3</sup>"] = "Cubic millimetre", ["cm<sup>3</sup>"] = "Cubic centimetre", ["dm<sup>3</sup>"] = "Cubic decimetre", ["dam<sup>3</sup>"] = "Cubic decametre", ["km<sup>3</sup>"] = "Cubic kilometre", ["μL"] = "Microlitre", ["μl"] = "Microlitre", ["mL"] = "Millilitre", ["ml"] = "Millilitre", ["cL"] = "Centilitre", ["cl"] = "Centilitre", ["dL"] = "Decilitre", ["dl"] = "Decilitre", ["daL"] = "Decalitre", ["dal"] = "Decalitre", ["hL"] = "Hectolitre", ["hl"] = "Hectolitre", ["kL"] = "Kilolitre", ["kl"] = "Kilolitre", ["ML"] = "Megalitre", ["Ml"] = "Megalitre", ["GL"] = "Gigalitre", ["Gl"] = "Gigalitre", ["TL"] = "Teralitre", ["Tl"] = "Teralitre", ["PL"] = "Petalitre", ["Pl"] = "Petalitre", } --------------------------------------------------------------------------- -- Do not change the data in this table because it is created by running -- -- a script that reads the wikitext from a wiki page (see note above). -- --------------------------------------------------------------------------- local per_unit_fixups = { -- Automatically created per units of form "x/y" may have their unit type -- changed, for example, "length/time" is changed to "speed". -- Other adjustments can also be specified. ["/area"] = "per unit area", ["/volume"] = "per unit volume", ["area/area"] = "area per unit area", ["energy/length"] = "energy per unit length", ["energy/mass"] = "energy per unit mass", ["energy/time"] = { utype = "power", link = "Power (physics)" }, ["energy/volume"] = "energy per unit volume", ["force/area"] = { utype = "pressure", link = "Pressure" }, ["length/length"] = { utype = "gradient", link = "Grade (slope)" }, ["length/time"] = { utype = "speed", link = "Speed" }, ["length/time/time"] = { utype = "acceleration", link = "Acceleration" }, ["mass/area"] = { utype = "pressure", multiplier = 9.80665 }, ["mass/length"] = "linear density", ["mass/mass"] = "concentration", ["mass/power"] = "mass per unit power", ["mass/time"] = "mass per unit time", ["mass/volume"] = { utype = "density", link = "Density" }, ["power/mass"] = "power per unit mass", ["power/volume"] = { link = "Power density" }, ["pressure/length"] = "fracture gradient", ["speed/time"] = { utype = "acceleration", link = "Acceleration" }, ["volume/area"] = "volume per unit area", ["volume/length"] = "volume per unit length", ["volume/time"] = "flow", } return { all_units = all_units, default_exceptions = default_exceptions, link_exceptions = link_exceptions, per_unit_fixups = per_unit_fixups, } df9e48c56b5ed9957eaef10e36df353b161075f5 Module:Convert/text 828 48 111 2022-02-13T04:01:17Z Canopus >Johnuniq 0 update from sandbox per [[Template talk:Convert#Module version 27]] Scribunto text/plain -- Text used by Module:Convert for enwiki. -- This is a separate module to simplify translation for use on another wiki. -- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki. -- Some units accept an SI prefix before the unit code, such as "kg" for kilogram. local SIprefixes = { -- The prefix field is what the prefix should be, if different from the prefix used. ['Y'] = { exponent = 24, name = 'yotta', }, ['Z'] = { exponent = 21, name = 'zetta', }, ['E'] = { exponent = 18, name = 'exa' , }, ['P'] = { exponent = 15, name = 'peta' , }, ['T'] = { exponent = 12, name = 'tera' , }, ['G'] = { exponent = 9, name = 'giga' , }, ['M'] = { exponent = 6, name = 'mega' , }, ['k'] = { exponent = 3, name = 'kilo' , }, ['h'] = { exponent = 2, name = 'hecto', }, ['da']= { exponent = 1, name = 'deca' , name_us = 'deka' }, ['d'] = { exponent = -1, name = 'deci' , }, ['c'] = { exponent = -2, name = 'centi', }, ['m'] = { exponent = -3, name = 'milli', }, ['μ'] = { exponent = -6, name = 'micro', }, -- key = 'GREEK SMALL LETTER MU' (U+03BC) utf-8 CE BC ['µ'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- key = 'MICRO SIGN' (U+00B5) utf-8 C2 B5 ['u'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- not an SI prefix, but allow for people typing this ['n'] = { exponent = -9, name = 'nano' , }, ['p'] = { exponent =-12, name = 'pico' , }, ['f'] = { exponent =-15, name = 'femto', }, ['a'] = { exponent =-18, name = 'atto' , }, ['z'] = { exponent =-21, name = 'zepto', }, ['y'] = { exponent =-24, name = 'yocto', }, } -- Some units can be qualified with one of the following prefixes, when linked. local customary_units = { { "US", link = "United States customary units" }, { "U.S.", link = "United States customary units" }, { "imperial", link = "Imperial units" }, { "imp", link = "Imperial units" }, } -- Names when using engineering notation (a prefix of "eN" where N is a number; example "e6km"). -- key = { "name", link = "article title", exponent = numeric_key_value } -- If lk=on and link is defined, the name of the number will appear as a link. local eng_scales = { ["3"] = { "thousand", exponent = 3 }, ["6"] = { "million", exponent = 6 }, ["9"] = { "billion", link = "1000000000 (number)", exponent = 9 }, ["12"] = { "trillion", link = "1000000000000 (number)", exponent = 12 }, ["15"] = { "quadrillion", link = "1000000000000000 (number)", exponent = 15 }, } local all_categories = { unit = "[[Category:Convert errors]]", option = "[[Category:Convert errors]]", warning = '[[Category:Convert invalid options]]', tracking = '[[Category:Convert tracking]]', } -- For some error messages, the following puts the wanted style around -- each unit code marked like '...%{ft%}...'. local unitcode_regex = '%%([{}])' local unitcode_replace = { ['{'] = '"', ['}'] = '"' } -- no longer need the more elaborate substitute used before 2013-09-28 -- All messages that may be displayed if a problem occurs. local all_messages = { -- Message format string: $1=title, $2=text, $3=category, $4=anchor. -- Each displayed message starts with "Convert:" so can easily locate by searching article. cvt_format = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[<i>[[Help:Convert messages#$4|<span title="Convert: $1">convert: $2</span>]]</i>]</sup>$3<span class="error"></span>', cvt_format2 = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[[Help:Convert messages#$4|<span title="Convert: $1">$2</span>]]</sup>$3<span class="error"></span>', cvt_format_preview = '<strong class="error">Error in convert: $1 [[Help:Convert messages#$4|(help)]]</strong>$3', -- Each of following messages is a table: -- { [1] = 'title', -- mouseover title text -- [2] = 'text', -- link text displayed in article -- [3] = 'category key', -- key to lookup category in all_categories -- [4] = 'anchor', -- anchor for link to relevant section on help page -- regex = gsub_regex, -- replace = gsub_table, -- } Mouseover title text Link text CatKey Anchor cvt_bad_input = { 'input "$1" must be a number and unit' , 'invalid input' , 'option', 'invalid_input' }, cvt_bad_num = { 'Value "$1" must be a number' , 'invalid number' , 'option', 'invalid_number' }, cvt_big_prec = { 'Precision "$1" is too large' , 'precision too large' , 'option', 'precision_too_large' }, cvt_invalid_num = { 'Number has overflowed' , 'number overflow' , 'option', 'number_overflow' }, cvt_no_num = { 'Needs the number to be converted' , 'needs a number' , 'option', 'needs_number' }, cvt_no_num2 = { 'Needs another number for a range' , 'needs another number', 'option', 'needs_another_number' }, cvt_bad_altitude = { '"$1" needs an integer' , 'invalid altitude' , 'option', 'invalid_altitude' }, cvt_bad_frac = { '"$1" needs an integer above 1' , 'invalid fraction' , 'option', 'invalid_fraction' }, cvt_bad_prec = { 'Precision "$1" must be an integer' , 'invalid precision' , 'option', 'invalid_precision' }, cvt_bad_sigfig = { '"$1" needs a positive integer' , 'invalid sigfig' , 'option', 'invalid_sigfig' }, cvt_empty_option = { 'Ignored empty option "$1"' , 'empty option' , 'option', 'empty_option' }, cvt_deprecated = { 'Option "$1" is deprecated' , '*' , 'option', 'deprecated_option', format = 'cvt_format2', nowarn = true }, cvt_no_spell = { 'Spelling is not available' , 'bug, ask for help' , 'option', 'ask_for_help' }, cvt_unknown_option = { 'Ignored invalid option "$1"' , 'invalid option' , 'option', 'invalid_option' }, cvt_wd_fail = { 'Unable to access Wikidata' , 'wikidata problem' , 'option', 'wikidata_problem' }, cvt_bad_default = { 'Unit "$1" has an invalid default' , 'bug, ask for help' , 'unit' , 'ask_for_help' }, cvt_bad_unit = { 'Unit "$1" is invalid here' , 'unit invalid here' , 'unit' , 'unit_invalid_here' }, cvt_no_default = { 'Unit "$1" has no default output unit' , 'bug, ask for help' , 'unit' , 'ask_for_help' }, cvt_no_unit = { 'Needs name of unit' , 'needs unit name' , 'unit' , 'needs_unit_name' }, cvt_unknown = { 'Unit name "$1" is not known' , 'unknown unit' , 'unit' , 'unknown_unit' }, cvt_should_be = { '$1' , 'ambiguous unit' , 'unit' , 'ambiguous_unit', regex = unitcode_regex, replace = unitcode_replace }, cvt_mismatch = { 'Cannot convert "$1" to "$2"' , 'unit mismatch' , 'unit' , 'unit_mismatch' }, cvt_bug_convert = { 'Bug: Cannot convert between specified units', 'bug, ask for help' , 'unit' , 'ask_for_help' }, cvt_lookup = { 'Unit "$1" is incorrectly defined' , 'bug, ask for help' , 'unit' , 'ask_for_help' }, } -- Text to join input value/unit with output value/unit. local disp_joins = { -- [1]=before output, [2]=after output, [3]=between outputs in a combination; default "; " -- [wantname] gives default abbr=off ["or"] = { " or " , "" , " or ", wantname = true }, ["sqbr-sp"] = { " [" , "]" }, ["sqbr-nbsp"] = { "&nbsp;[" , "]" }, ["comma"] = { ", " , "" , ", " }, ["slash-sp"] = { " / " , "" , wantname = true }, ["slash-nbsp"] = { "&nbsp;/ ", "" , wantname = true }, ["slash-nosp"] = { "/" , "" , wantname = true }, ["b"] = { " (" , ")" }, ["(or)"] = { " (" , ")", " or " }, ["br"] = { "<br />" , "" , wantname = true }, ["br()"] = { "<br />(" , ")", wantname = true }, } -- Text to separate values in a range. local range_types = { -- Specifying a table requires either: -- * "off" and "on" values (for "abbr=off" and "abbr=on"), or -- * "input" and "output" values (for LHS and RHS); -- other fields are optional. -- When "adj=on|abbr=off" applies, spaces in range text are replaced with hyphens. -- With "exception = true", that also occurs with "adj=on|abbr=on". -- If "adj" is defined here, that text (unchanged) is used with "adj=on". ["+"] = " + ", [","] = ",&nbsp;", [", and"] = ", and ", [", or"] = ", or ", ["by"] = " by ", ["-"] = "–", ["to about"] = " to about ", ["and"] = { off = " and ", on = " and ", exception = true }, ["and(-)"] = { input = " and ", output = "–" }, ["or"] = { off = " or " , on = " or " , exception = true }, ["to"] = { off = " to " , on = " to " , exception = true }, ["to(-)"] = { input = "&nbsp;to ", output = "–" }, ["+/-"] = { off = "&nbsp;±&nbsp;", on = "&nbsp;±&nbsp;", adj = "&nbsp;±&nbsp;", is_range_change = true }, ["by(x)"] = { input = " by ", output = " ×&nbsp;", out_range_x = true }, ["x"] = { off = " by ", on = " ×&nbsp;", abbr_range_x = true }, ["xx"] = "&nbsp;×&nbsp;", ["*"] = "×", ["/"] = "&thinsp;/&thinsp;", -- for a table of high/low temperatures with {{convert|83|/|63|F|disp=br()|abbr=values}} } local range_aliases = { -- ["alternative name for a range"] = "standard range name" ["–"] = "-", ["&ndash;"] = "-", ["×"] = "x", ["&times;"] = "x", ["±"] = "+/-", ["&plusmn;"] = "+/-", } -- Convert accepts range text delimited with whitespace, for example, {{convert|1 to 2|ft}}. -- In addition, the following "words" are accepted without spaces, for example, {{convert|1-2|ft}}. -- Words must be in correct order for searching, for example, 'x' after 'xx'. local range_words = { '-', '–', 'xx', 'x', '*' } local ranges = { types = range_types, aliases = range_aliases, words = range_words, } -- Valid option names. local en_option_name = { -- ["local text for option name"] = "en name used in this module" ["$"] = "$", ["abbr"] = "abbr", ["adj"] = "adj", ["altitude_ft"] = "altitude_ft", ["altitude_m"] = "altitude_m", ["comma"] = "comma", ["debug"] = "debug", ["disp"] = "disp", ["frac"] = "frac", ["input"] = "input", ["lang"] = "lang", ["lk"] = "lk", ["order"] = "order", ["qid"] = "qid", ["qual"] = "qual", ["qualifier"] = "qual", ["round"] = "round", ["sigfig"] = "sigfig", ["sing"] = "adj", -- "sing" is an old alias for "adj" ["sortable"] = "sortable", ["sp"] = "sp", ["spell"] = "spell", ["stylein"] = "stylein", ["styleout"] = "styleout", ["tracking"] = "tracking", } -- Valid option values. -- Convention: parms.opt_xxx refers to an option that is set here -- (not intended to be set by the template which invokes this module). -- Example: At enwiki, "abbr" includes: -- ["values"] = "opt_values" -- As a result, if the template uses abbr=values, Module:Convert sets: -- parms["opt_values"] = true -- parms["abbr"] = nil -- Therefore parms.abbr will be nil, or will have one of the listed values -- that do not start with "opt_". -- An option value of form "xxx?" is the same as "xxx" but shows the input as deprecated. local en_option_value = { ["$"] = 'TEXT', -- TEXT should be a currency symbol that will be used instead of "$" ["abbr"] = { -- ["local text for option value"] = "en value used in this module" ["def"] = "", -- ignored (some wrapper templates call convert with "abbr=def" to mean "default abbreviation") ["h"] = "on", -- abbr=on + use "h" for hand unit (default) ["hh"] = "opt_hand_hh", -- abbr=on + use "hh" for hand unit ["in"] = "in", -- use symbol for LHS unit ["none"] = "off", -- old name for "off" ["off"] = "off", -- use name for all units ["on"] = "on", -- use symbol for all units ["out"] = "out", -- use symbol for RHS unit (default) ["unit"] = "unit", -- abbr=on but abbreviate units only: e6km → million km (not ×10⁶ km) ["values"] = "opt_values", -- show only input and output numbers, not units ["~"] = "opt_also_symbol", -- show input unit symbol as well as name }, ["adj"] = { ["mid"] = "opt_adjectival, opt_adj_mid", -- adj=on with user-specified text after input unit (between input and output) ["off"] = "", -- ignored (off is the default) ["on"] = "opt_adjectival", -- unit name is singular and hyphenated ["pre"] = "opt_one_preunit", -- user-specified text before input unit ["ri0"] = "opt_ri=0", -- round input with precision = 0 ["ri1"] = "opt_ri=1", -- round input with precision = 1 ["ri2"] = "opt_ri=2", -- round input with precision = 2 ["ri3"] = "opt_ri=3", -- round input with precision = 3 }, ["altitude_ft"] = 'INTEGER', ["altitude_m"] = 'INTEGER', ["comma"] = { ["5"] = "opt_comma5", -- only use numsep grouping if 5 or more digits ["gaps"] = "opt_gaps", -- use gaps, not numsep, to separate groups of digits ["gaps3"] = "opt_gaps, opt_gaps3", -- group only in threes rather than default of no gap before a single digit after decimal mark ["off"] = "opt_nocomma", -- no numsep in input or output numbers }, ["debug"] = { ["yes"] = "opt_sortable_debug", -- make the normally hidden sort key visible }, ["disp"] = { ["5"] = "opt_round=5?", -- round output value to nearest 5 ["b"] = "b", -- join: '(...)' ["(or)"] = "(or)", -- join: '(...)' with 'or' between outputs in a combination ["br"] = "br", -- join: '<br />' ["br()"] = "br()", -- join: '<br />(...)' ["comma"] = "comma", -- join: ',' ["flip"] = "opt_flip", -- reverse order of input/output ["number"] = "opt_output_number_only", -- display output value (not input, and not output symbol/name) ["or"] = "or", -- join: 'or' ["out"] = "opt_output_only", ["output number only"] = "opt_output_number_only", ["output only"] = "opt_output_only", ["preunit"] = "opt_two_preunits", -- user-specified text before input and output units ["sqbr"] = "sqbr", -- join: '[...]' ["table"] = "opt_table", -- output is suitable for a table cell with align="right" ["tablecen"] = "opt_tablecen", -- output is suitable for a table cell with align="center" ["unit"] = "opt_input_unit_only", -- display input symbol/name (not output, and not input value) ["unit or text"] = "opt_input_unit_only, opt_ignore_error", -- display input symbol/name, or given unit code if not known ["unit2"] = "opt_output_unit_only", ["x"] = "x", -- join: <first>...<second> (user-specified text) }, ["frac"] = 'INTEGER', ["input"] = 'TEXT', -- TEXT should be value><space><unitcode> or <wikidata-property-id> ["lang"] = { -- language for output digits (both en and local digits are always accepted for input) ["en"] = "opt_lang_en", -- use en digits for numbers, regardless of local language ["local"] = "opt_lang_local", -- use local digits for numbers (default, although config can change default to en) }, ["lk"] = { ["in"] = "in", -- link LHS unit name or symbol ["off"] = "off", -- do not link: same as default except for hand unit ["on"] = "on", -- link all unit names or symbols (but not twice for the same unit) ["out"] = "out", -- link RHS unit name or symbol }, ["order"] = { ["flip"] = "opt_flip", -- reverse order of input/output ["out"] = "opt_order_out", -- do not show input; instead, use order in output combination, with the first output shown as the input }, ["qid"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier ["qual"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier ["round"] = { ["0.5"] = "opt_round=0.5", -- round output value to nearest 0.5 ["5"] = "opt_round=5", -- round output value to nearest 5 ["10"] = "opt_round=10", -- round output value to nearest 10 (same as but clearer than "|-1") ["25"] = "opt_round=25", -- round output value to nearest 25 ["50"] = "opt_round=50", -- round output value to nearest 50 ["each"] = "opt_round_each", -- using default precision in a range, round each output separately (default uses highest precision of each item in range) }, ["sigfig"] = 'INTEGER', ["sortable"] = { ["off"] = "", -- ignored (off is the default) ["on"] = "opt_sortable_on", -- output sort key for use in a sortable table, based on value from converting to a standard base unit ["debug"] = "opt_sortable_on, opt_sortable_debug", -- |sortable=debug is the same as |sortable=on|debug=yes }, ["sp"] = { ["us"] = "opt_sp_us", -- use U.S. spelling (like "meter" instead of default "metre") }, ["spell"] = { -- only English spelling is supported; not scientific notation; only some fractions ["in"] = "opt_spell_in", -- spell input value in words ["In"] = "opt_spell_in, opt_spell_upper", -- spell input value in words with first letter uppercase ["on"] = "opt_spell_in, opt_spell_out", -- spell input and output values in words ["On"] = "opt_spell_in, opt_spell_out, opt_spell_upper", -- same, with first letter of first word in result uppercase }, ["stylein"] = 'TEXT', ["styleout"] = 'TEXT', ["tracking"] = 'TEXT', } local titles = { ["frac"] = "Fraction/styles.css", ["sfrac"] = "Sfrac/styles.css", } return { SIprefixes = SIprefixes, all_categories = all_categories, all_messages = all_messages, currency = { ['$'] = true, ['£'] = true, ['€'] = true, ['₱'] = true, ['₽'] = true, ['¥'] = true }, customary_units = customary_units, disp_joins = disp_joins, en_option_name = en_option_name, en_option_value = en_option_value, eng_scales = eng_scales, ranges = ranges, titles = titles, } 05665ce7dee224b4474fd898266e157aab84691f Template:End 10 144 303 2022-02-20T11:17:15Z Canopus >Gonnym 0 Undid revision 1072975485 by [[Special:Contributions/Gonnym|Gonnym]] ([[User talk:Gonnym|talk]]) wikitext text/x-wiki <includeonly> {{#if:{{{html|}}}|</table>|{{!}}} }}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using end template with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:End]] with unknown parameter "_VALUE_"|ignoreblank=y| html | 1<!--parameter does not do anything, but described in the documentation since 2015--> }}<noinclude>{{Documentation}}</noinclude> 6da317c960412bc7ac63866ddd9237d1a9bd914e Module:Check for unknown parameters 828 70 155 2022-02-21T05:24:13Z Canopus >BusterD 0 Changed protection settings for "[[Module:Check for unknown parameters]]": [[WP:High-risk templates|Highly visible template]]; requested at [[WP:RfPP]] ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite)) Scribunto text/plain -- This module may be used to compare the arguments passed to the parent -- with a list of arguments, returning a specified result if an argument is -- not on the list local p = {} local function trim(s) return s:match('^%s*(.-)%s*$') end local function isnotempty(s) return s and s:match('%S') end local function clean(text) -- Return text cleaned for display and truncated if too long. -- Strip markers are replaced with dummy text representing the original wikitext. local pos, truncated local function truncate(text) if truncated then return '' end if mw.ustring.len(text) > 25 then truncated = true text = mw.ustring.sub(text, 1, 25) .. '...' end return mw.text.nowiki(text) end local parts = {} for before, tag, remainder in text:gmatch('([^\127]*)\127[^\127]*%-(%l+)%-[^\127]*\127()') do pos = remainder table.insert(parts, truncate(before) .. '&lt;' .. tag .. '&gt;...&lt;/' .. tag .. '&gt;') end table.insert(parts, truncate(text:sub(pos or 1))) return table.concat(parts) end function p._check(args, pargs) if type(args) ~= "table" or type(pargs) ~= "table" then -- TODO: error handling return end -- create the list of known args, regular expressions, and the return string local knownargs = {} local regexps = {} for k, v in pairs(args) do if type(k) == 'number' then v = trim(v) knownargs[v] = 1 elseif k:find('^regexp[1-9][0-9]*$') then table.insert(regexps, '^' .. v .. '$') end end -- loop over the parent args, and make sure they are on the list local ignoreblank = isnotempty(args['ignoreblank']) local showblankpos = isnotempty(args['showblankpositional']) local values = {} for k, v in pairs(pargs) do if type(k) == 'string' and knownargs[k] == nil then local knownflag = false for _, regexp in ipairs(regexps) do if mw.ustring.match(k, regexp) then knownflag = true break end end if not knownflag and ( not ignoreblank or isnotempty(v) ) then table.insert(values, clean(k)) end elseif type(k) == 'number' and knownargs[tostring(k)] == nil then local knownflag = false for _, regexp in ipairs(regexps) do if mw.ustring.match(tostring(k), regexp) then knownflag = true break end end if not knownflag and ( showblankpos or isnotempty(v) ) then table.insert(values, k .. ' = ' .. clean(v)) end end end -- add results to the output tables local res = {} if #values > 0 then local unknown_text = args['unknown'] or 'Found _VALUE_, ' if mw.getCurrentFrame():preprocess( "{{REVISIONID}}" ) == "" then local preview_text = args['preview'] if isnotempty(preview_text) then preview_text = require('Module:If preview')._warning({preview_text}) elseif preview == nil then preview_text = unknown_text end unknown_text = preview_text end for _, v in pairs(values) do -- Fix odd bug for | = which gets stripped to the empty string and -- breaks category links if v == '' then v = ' ' end -- avoid error with v = 'example%2' ("invalid capture index") local r = unknown_text:gsub('_VALUE_', {_VALUE_ = v}) table.insert(res, r) end end return table.concat(res) end function p.check(frame) local args = frame.args local pargs = frame:getParent().args return p._check(args, pargs) end return p 93db6d115d4328d2a5148bb42959105e367b663e Module:ResolveEntityId 828 92 199 2022-03-03T02:11:37Z Canopus >Ahecht 0 Sync from sandbox. Follow Wikipedia redirects, remove _entityid() function. Feel free to revert if any more issues crop up. Scribunto text/plain local p = {} function p._id(idOrTitle, alt) local function checkId(id) if id and mw.wikibase.entityExists(id) then local sitelink = mw.wikibase.getSitelink(id) if sitelink then return mw.wikibase.getEntityIdForTitle(sitelink) or mw.wikibase.getEntity(id).id end return mw.wikibase.getEntity(id).id else return alt end end if type(idOrTitle) == 'string' then idOrTitle = mw.ustring.upper(mw.ustring.sub(idOrTitle, 1, 1)) .. mw.ustring.sub(idOrTitle, 2) if mw.wikibase.isValidEntityId(idOrTitle) then -- idOrTitle is in the proper format for a Wikidata entity ID return checkId(idOrTitle) else local eid = mw.wikibase.getEntityIdForTitle(idOrTitle) if eid then -- idOrTitle is a title that matches a Wikidata entity local instanceOf = mw.wikibase.getBestStatements(eid, 'P31')[1] --instance of if not instanceOf or instanceOf.mainsnak.datavalue.value.id ~= 'Q4167410' then -- instance-of value is missing or is not "disambiguation" return checkId(eid) end else -- idOrTitle is a title, but no wikidata item exists for that title local rtarget = mw.title.new(idOrTitle).redirectTarget if rtarget then -- title is a Wikipedia redirect return p._id(rtarget.fullText, alt) end end end end return alt end function p.entityid(frame) return p._id(frame.args[1], frame.args[2]) end return p 520d9c0247df2692f8909c86f05c6eb7aab182c0 Template:Starbox astrometry 10 152 319 2022-04-03T19:25:52Z Canopus >Paine Ellsworth 0 per edit requests on talk page - footnote placements + remove all instances of the "small" tag to improve accessibility wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><th style="background-color: #FFFFC0; text-align: center;" colspan="2">{{#if:{{{no_heading|}}}||[[Astrometry]]}}</th></tr>{{#if:{{{component|}}}|<tr style="text-align:center"><th colspan="2">{{{component}}}</th></tr>}}</th></tr><!-- --><tr><th colspan="2" style="text-align: center">{{{component1<includeonly>|</includeonly>}}}</tr><!-- -->{{#if:{{{radial_v<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Radial velocity]] (R<sub>v</sub>)'''</td><td>{{{radial_v}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{total_v<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''Total velocity'''</td><td>{{{total_v}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{prop_mo_ra<includeonly>|</includeonly>}}}{{{prop_mo_dec|}}}|<tr style="vertical-align:top;"><td>'''[[Proper motion]] (μ)'''</td><td> <abbr title="Right Ascension">RA:</abbr>&nbsp;{{{prop_mo_ra|}}}&nbsp;[[Milliarcsecond|mas]]/[[Year|yr]]{{{pm_footnote|}}} <br /> <abbr title="Declination">Dec.:</abbr>&nbsp;{{{prop_mo_dec|}}}&nbsp;[[Milliarcsecond|mas]]/[[Year|yr]]{{{pm_footnote|}}} </td></tr> }}<!-- -->{{#if:{{{parallax<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Stellar parallax|Parallax]] (π)'''</td><td>{{{parallax}}}{{#if:{{{p_error|}}}|&nbsp;±&nbsp;{{{p_error}}} }}&nbsp;[[Milliarcsecond|mas]]{{#if:{{{parallax_footnote|}}}|{{{parallax_footnote}}} }}</td></tr>}}<!-- -->{{#if:{{{dist_ly<includeonly>|</includeonly>}}}{{{dist_pc|}}}{{#if:{{{parallax|}}}|{{#if:{{{p_error|}}}|{{#ifexpr: {{{parallax|}}}-{{{p_error|}}}>0|yes}}}}}}|<tr style="vertical-align:top;"><td>'''[[Distance (astronomy)|Distance]]'''</td><!-- --><td><!-- -->{{#if:{{{dist_ly<includeonly>|</includeonly>}}}{{{dist_pc|}}}||{{ErrorBar2|{{#expr: 3261.5638 / {{{parallax}}} }}|{{#if:{{{p_error|}}}|{{#expr: 3261.5638 * {{{p_error}}} / ({{{parallax}}} * {{{parallax}}}) }} }}|0.1}}&nbsp;[[Light-year|ly]] <br />({{ErrorBar2|{{#expr: 1000.0 / {{{parallax}}} }}|{{#if:{{{p_error|}}}|{{#expr: 1000.0 * {{{p_error}}} / ({{{parallax}}} * {{{parallax}}}) }} }}|0.1}}&nbsp;[[Parsec|pc]])}}<!-- -->{{#if:{{{dist_ly<includeonly>|</includeonly>}}}|{{{dist_ly}}}&nbsp;[[Light-year|ly]] {{#if:{{{dist_pc|}}}|<br />({{{dist_pc}}}&nbsp;[[Parsec|pc]])}}|{{#if:{{{dist_pc|}}}|{{{dist_pc}}}&nbsp;[[Parsec|pc]]}}}}{{{dist_footnote|}}}<!-- --></td></tr>}}<!-- -->{{#if:{{{absmag_v<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Absolute magnitude|Absolute&nbsp;magnitude]]&nbsp;(M<sub>V</sub>)'''</td><td>{{{absmag_v}}}</td></tr>}}<!-- -->{{#if:{{{absmag_bol<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Absolute magnitude|Absolute&nbsp;bolometric<br>magnitude]]&nbsp;(M<sub>bol</sub>)'''</td><td>{{{absmag_bol}}}</td></tr>}}<!-- --><tr><th colspan="2" style="text-align: center">{{{component2<includeonly>|</includeonly>}}}</th></tr><!-- -->{{#if:{{{radial_v2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Radial velocity]] (R<sub>v</sub>)'''</td><td>{{{radial_v2}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{total_v2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''Total velocity'''</td><td>{{{total_v2}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{prop_mo_ra2<includeonly>|</includeonly>}}}{{{prop_mo_dec2|}}}|<tr style="vertical-align:top;"><td>'''[[Proper motion]] (μ)'''</td><td> <abbr title="Right Ascension">RA:</abbr>&nbsp;{{{prop_mo_ra2|-}}}&nbsp;[[Milliarcsecond|mas]]/[[Year|yr]]{{{pm_footnote2|}}} <br /> <abbr title="Declination">Dec.:</abbr>&nbsp;{{{prop_mo_dec2|-}}}&nbsp;[[Milliarcsecond|mas]]/[[Year|yr]]{{{pm_footnote2|}}} </td></tr> }}<!-- -->{{#if:{{{parallax2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Stellar parallax|Parallax]] (π)'''</td><td>{{{parallax2}}}{{#if:{{{p_error2|}}}|&nbsp;±&nbsp;{{{p_error2}}}}}&nbsp;[[Milliarcsecond|mas]]{{#if:{{{parallax_footnote2|}}}|{{{parallax_footnote2}}}}}</td></tr>}}<!-- -->{{#if:{{{dist_ly2<includeonly>|</includeonly>}}}{{{dist_pc2|}}}{{{parallax2|}}}|<tr style="vertical-align:top;"><td>'''[[Distance (astronomy)|Distance]]'''</td><!-- --><td><!-- -->{{#if:{{{dist_ly2<includeonly>|</includeonly>}}}{{{dist_pc2|}}}||{{ErrorBar2|{{#expr: 3261.5638 / {{{parallax2}}} }}|{{#if:{{{p_error2|}}}|{{#expr: 3261.5638 * {{{p_error2}}} / ({{{parallax2}}} * {{{parallax2}}}) }} }}|0.1}}&nbsp;[[Light-year|ly]] <br />({{ErrorBar2|{{#expr: 1000.0 / {{{parallax2}}} }}|{{#if:{{{p_error2|}}}|{{#expr: 1000.0 * {{{p_error2}}} / ({{{parallax2}}} * {{{parallax2}}}) }} }}|0.1}}&nbsp;[[Parsec|pc]])}}<!-- -->{{#if:{{{dist_ly<includeonly>|</includeonly>}}}|{{{dist_ly2}}}&nbsp;[[Light-year|ly]] {{#if:{{{dist_pc2|}}}|<br />({{{dist_pc2}}}&nbsp;[[Parsec|pc]])}}|{{#if:{{{dist_pc2|}}}|{{{dist_pc2}}}&nbsp;[[Parsec|pc]]}}}}<!-- --></td></tr>}}<!-- -->{{#if:{{{absmag_v2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Absolute magnitude|Absolute&nbsp;magnitude]]&nbsp;(M<sub>V</sub>)'''</td><td>{{{absmag_v2}}}</td></tr>}}<!-- -->{{#if:{{{absmag_bol2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Absolute magnitude|Absolute&nbsp;bolometric<br>magnitude]]&nbsp;(M<sub>bol</sub>)'''</td><td>{{{absmag_bol2}}}</td></tr>}}<noinclude> |} {{Documentation}} </noinclude> e92454f250713fd8ce29da215c7da5e8ac87b802 Template:If empty 10 93 201 2022-04-03T20:56:41Z Canopus >Wugapodes 0 Changed protection settings for "[[Template:If empty]]": [[WP:High-risk templates|Highly visible template]]: used on 2 million pages and permanently cascade protected; matches module protection ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite)) wikitext text/x-wiki {{<includeonly>safesubst:</includeonly>#invoke:If empty|main}}<noinclude>{{Documentation}}</noinclude> 745940b7bdde8a1585c887ee4ee5ce81d98461a4 Template:Starbox character 10 155 325 2022-04-04T18:15:01Z Canopus >Paine Ellsworth 0 per edit request at [[Template talk:Starbox begin#Template-protected edit request on 3 April 2022]] - remove small tags wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude> |- ! style="background-color: #FFFFC0; text-align: center;" colspan="2"| {{#if:{{{no_heading|}}}||Characteristics}} |- {{#if:{{{component|}}}| ! style="text-align:center" colspan="2" {{!}} {{{component}}} }} |- {{#if:{{{component1|}}}| ! style="text-align:center" colspan="2" {{!}} {{{component1}}} }} |- style="vertical-align:top" {{#if:{{{type|}}}| ! style="text-align:left" {{!}} [[Stellar evolution|Evolutionary&nbsp;stage]] {{!}} {{{type}}} }} |- style="vertical-align:top" {{#if:{{{class|}}}| ! style="text-align:left" {{!}} [[Stellar classification|Spectral&nbsp;type]] {{!}} {{{class}}} }} |- style="vertical-align:top" {{#if:{{{appmag_1_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude]]&nbsp;({{{appmag_1_passband|}}}) {{!}} {{{appmag_1}}} }} |- style="vertical-align:top" {{#if:{{{appmag_2_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_2_passband|}}}) {{!}} {{{appmag_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_3_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_3_passband|}}}) {{!}} {{{appmag_3}}} }} |- style="vertical-align:top" {{#if:{{{appmag_4_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_4_passband|}}}) {{!}} {{{appmag_4}}} }} |- style="vertical-align:top" {{#if:{{{appmag_5_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_5_passband|}}}) {{!}} {{{appmag_5}}} }} |- style="vertical-align:top" {{#if:{{{appmag_6_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_6_passband|}}}) {{!}} {{{appmag_6}}} }} |- style="vertical-align:top" {{#if:{{{appmag_7_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_7_passband|}}}) {{!}} {{{appmag_7}}} }} |- style="vertical-align:top" {{#if:{{{appmag_8_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_8_passband|}}}) {{!}} {{{appmag_8}}} }} |- style="vertical-align:top" {{#if:{{{u-b|}}}| ! style="text-align:left" {{!}} U−B {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{u-b}}} }} |- style="vertical-align:top" {{#if:{{{b-v|}}}| ! style="text-align:left" {{!}} B−V {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{b-v}}} }} |- style="vertical-align:top" {{#if:{{{v-r|}}}| ! style="text-align:left" {{!}} V−R {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{v-r}}} }} |- style="vertical-align:top" {{#if:{{{r-i|}}}| ! style="text-align:left" {{!}} R−I {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{r-i}}} }} |- style="vertical-align:top" {{#if:{{{j-h|}}}| ! style="text-align:left" {{!}} J−H {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{j-h}}} }} |- style="vertical-align:top" {{#if:{{{j-k|}}}| ! style="text-align:left" {{!}} J−K {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{j-k}}} }} |- style="vertical-align:top" {{#if:{{{variable|}}}| ! style="text-align:left" {{!}} [[Variable star|Variable&nbsp;type]] {{!}} {{{variable}}} }} |- style="vertical-align:top" {{#if:{{{component2|}}}| ! style="text-align:center" colspan="2" {{!}} {{{component2}}} }} |- style="vertical-align:top" {{#if:{{{type2|}}}| ! style="text-align:left" {{!}} [[Stellar evolution|Evolutionary&nbsp;stage]] {{!}} {{{type2}}} }} |- style="vertical-align:top" {{#if:{{{class2|}}}| ! style="text-align:left" {{!}} [[Stellar classification|Spectral&nbsp;type]] {{!}} {{{class2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_1_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude]]&nbsp;({{{appmag_1_passband2|}}}) {{!}} {{{appmag_1_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_2_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_2_passband2|}}}) {{!}} {{{appmag_2_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_3_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_3_passband2|}}}) {{!}} {{{appmag_3_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_4_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_4_passband2|}}}) {{!}} {{{appmag_4_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_5_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_5_passband2|}}}) {{!}} {{{appmag_5_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_6_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_6_passband2|}}}) {{!}} {{{appmag_6_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_7_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_7_passband2|}}}) {{!}} {{{appmag_7_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_8_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_8_passband2|}}}) {{!}} {{{appmag_8_2}}} }} |- style="vertical-align:top" {{#if:{{{u-b2|}}}| ! style="text-align:left" {{!}} U−B {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{u-b2}}} }} |- style="vertical-align:top" {{#if:{{{b-v2|}}}| ! style="text-align:left" {{!}} B−V {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{b-v2}}} }} |- style="vertical-align:top" {{#if:{{{v-r2|}}}| ! style="text-align:left" {{!}} V−R {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{v-r2}}} }} |- style="vertical-align:top" {{#if:{{{r-i2|}}}| ! style="text-align:left" {{!}} R−I {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{r-i2}}} }} |- style="vertical-align:top" {{#if:{{{j-h2|}}}| ! style="text-align:left" {{!}} J−H {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{j-h2}}} }} |- style="vertical-align:top" {{#if:{{{j-k2|}}}| ! style="text-align:left" {{!}} J−K {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{j-k2}}} }} |- style="vertical-align:top" {{#if:{{{variable2|}}}| ! style="text-align:left" {{!}} [[Variable star|Variable&nbsp;type]] {{!}} {{{variable2}}} }}<noinclude> |} {{Documentation}} </noinclude> bd7d2ca5352dd7b2dc3f58a1ac88cd9daf7194e3 Template:Starbox end 10 157 329 2022-04-04T18:21:34Z Canopus >Paine Ellsworth 0 add [[WP:RCAT|rcat template]] wikitext text/x-wiki #REDIRECT [[Template:End]] {{Rcat shell| {{Wikidata redirect}} {{R from template shortcut}} {{R with history}} }} ad342c0433bda993d648e9da241703291bbb98a6 Template:Starbox observe 10 159 333 2022-04-04T19:04:21Z Canopus >Paine Ellsworth 0 per edit request at [[Template talk:Starbox begin#Template-protected edit request on 3 April 2022]] - remove small tags wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude> |- ! style="text-align: center; background-color: #FFFFC0;" colspan="2" | Observation data<br/>{{#ifeq:{{{epoch}}}|[[J2000.0]] ([[International Celestial Reference System|ICRS]])|[[Epoch (astronomy)|Epoch]] [[J2000.0]]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[Equinox (celestial coordinates)|Equinox]] [[J2000.0]] ([[International Celestial Reference System|ICRS]])| [[Epoch (astronomy)|Epoch]] {{{epoch}}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[Equinox (celestial coordinates)|Equinox]] {{{equinox|{{{epoch|}}}}}}}} |- style="vertical-align:top" ! style="text-align:left" | [[Constellation]] | {{{constell}}} |- style="vertical-align:top" {{#if:{{{pronounce<includeonly>|</includeonly>}}}| ! style="text-align:left" {{!}} [[WP:IPA for English|Pronunciation]] {{!}} {{{pronounce}}} }} |- style="vertical-align:top" ! style="text-align:left" | {{nowrap|[[Right ascension]]}} | {{{ra}}} |- style="vertical-align:top" ! style="text-align:left" | [[Declination]] | {{{dec}}} |- style="vertical-align:top" {{#if:{{{appmag_v<includeonly>|</includeonly>}}}| ! style="text-align:left" {{!}} {{nowrap|[[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;(V)}} {{!}} {{{appmag_v}}} }}<noinclude> |} {{Documentation}} </noinclude> 21bf36f2041ff2d017e71e8c048693e9ad9e15db Template:Starbox reference 10 160 335 2022-05-03T09:40:55Z Canopus >Primefac 0 update SIMBAD links (TPER) wikitext text/x-wiki <noinclude> {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><th style="background-color: #FFFFC0; text-align: center;" colspan="2">{{#if:{{{no_heading|}}}||Database references}}</th></tr>{{#if:{{{component|}}}|<tr style="text-align:center"><th colspan="2">{{{component}}}</th></tr>}}<!-- -->{{#if:{{{Simbad<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td>'''[[SIMBAD]]'''</td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad}}} {{{sn|data}}}]</tr>}}<!-- -->{{#if:{{{Simbad2<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad2}}} {{{sn2|data2}}}]</tr>}}<!-- -->{{#if:{{{Simbad3<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad3}}} {{{sn3|data3}}}]</tr>}}<!-- -->{{#if:{{{Simbad4<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad4}}} {{{sn4|data4}}}]</tr>}}<!-- -->{{#if:{{{Simbad5<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad5}}} {{{sn5|data5}}}]</tr>}}<!-- -->{{#if:{{{Simbad6<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad6}}} {{{sn6|data6}}}]</tr>}}<!-- -->{{#if:{{{Simbad7<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad7}}} {{{sn7|data7}}}]</tr>}}<!-- -->{{#if:{{{Simbad8<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad8}}} {{{sn8|data8}}}]</tr>}}<!-- -->{{#if:{{{Simbad9<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad9}}} {{{sn9|data9}}}]</tr>}}<!-- -->{{#if:{{{NSTED<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td>'''[[Exoplanet Archive]]'''</td><td>[https://exoplanetarchive.ipac.caltech.edu/cgi-bin/DisplayOverview/nph-DisplayOverview?objname={{{NSTED}}} {{{nn|data}}}]</tr>}}<!-- -->{{#if:{{{NSTED2<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://exoplanetarchive.ipac.caltech.edu/cgi-bin/DisplayOverview/nph-DisplayOverview?objname={{{NSTED2}}} {{{nn2|data2}}}]</tr>}}<!-- -->{{#if:{{{NSTED3<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://exoplanetarchive.ipac.caltech.edu/cgi-bin/DisplayOverview/nph-DisplayOverview?objname={{{NSTED3}}} {{{nn3|data3}}}]</tr>}}<!-- -->{{#if:{{{ARICNS<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td>'''ARICNS'''</td><td>[https://wwwadd.zah.uni-heidelberg.de/datenbanken/aricns/cnspages/4c{{{ARICNS}}}.htm {{{an|data}}}]</td></tr>}}<!-- -->{{#if:{{{ARICNS2<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://wwwadd.zah.uni-heidelberg.de/datenbanken/aricns/cnspages/4c{{{ARICNS2}}}.htm {{{an2|data2}}}]</td></tr>}}<!-- -->{{#if:{{{ARICNS3<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://wwwadd.zah.uni-heidelberg.de/datenbanken/aricns/cnspages/4c{{{ARICNS3}}}.htm {{{an3|data3}}}]</td></tr>}}<!-- -->{{#if:{{{EPE<includeonly>|</includeonly>}}}|<tr><td>'''[[Extrasolar Planets Encyclopaedia|Extrasolar Planets<br />Encyclopaedia]]'''</td><td>[https://exoplanet.eu/star.php?st={{{EPE}}} data]</td></tr>}}<!-- -->{{#if:{{{KIC<includeonly>|</includeonly>}}}|<tr><td>'''[[Kepler Input Catalog|KIC]]'''</td><td>[https://archive.stsci.edu/kepler/data_search/search.php?action=Search&ktc_kepler_id={{{KIC}}} data]</td></tr> }}<noinclude> |} {{Documentation}} </noinclude> f84999acae32fc7dacb316605220d28af5b2f06d Module:If empty 828 94 203 2022-05-06T04:38:40Z Canopus >Dinoguy1000 0 update from sandbox, per [[Template talk:If empty#Backcompat]] Scribunto text/plain local p = {} function p.main(frame) local args = require('Module:Arguments').getArgs(frame, {wrappers = 'Template:If empty', removeBlanks = false}) local lastk = 0 for k,v in ipairs(args) do if v ~= '' then return v end lastk = k end end return p 4bfc0c7c8bf3b63144db1ea12f2260db00421233 Template:Cite Gaia DR2 10 163 341 2022-05-24T21:12:50Z Canopus >Lithopsian 0 attempt fix for leading space in the source ID (see talk page) wikitext text/x-wiki {{cite journal | last1=Brown | first1=A. G. A. | display-authors=etal | collaboration=Gaia collaboration | date=August 2018 | title=''Gaia'' Data Release 2: Summary of the contents and survey properties | journal=[[Astronomy & Astrophysics]] | volume=616 |at=A1 | arxiv=1804.09365 | bibcode=2018A&A...616A...1G | bibcode-access=free | doi=10.1051/0004-6361/201833051 | doi-access=free | mode={{{mode|}}} }}{{#if:{{{1|}}}|&#32;[http://vizier.u-strasbg.fr/viz-bin/VizieR-S?Gaia%20DR2%20{{Trim|{{{1|}}}}} Gaia DR2 record for this source] at [[VizieR]].}}<noinclude> {{Documentation}} </noinclude> f0d86754ae543ff75617b1a118b720534de42335 Module:Portal 828 64 143 2022-06-05T03:15:40Z Canopus >Hike395 0 extend image function to take border argument Scribunto text/plain --[==[ This module is a Lua implementation of the old {{Portal}} template. As of February 2019 it is used on nearly 7,900,000 articles. -- Please take care when updating it! It outputs two functions: p.portal, which generates a list of portals, and p.image, which -- produces the image name for an individual portal. -- The portal image data is kept in submodules of [[Module:Portal/images]], listed below: -- [[Module:Portal/images/a]] - for portal names beginning with "A". -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/o]] - for portal names beginning with "O". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/s]] - for portal names beginning with "S". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- [[Module:Portal/images/aliases]] - for adding aliases for existing portal names. Use this page for variations -- in spelling and diacritics, etc., no matter what letter the portal begins with. -- -- The images data pages are separated by the first letter to reduce server load when images are added, changed, or removed. -- Previously all the images were on one data page at [[Module:Portal/images]], but this had the disadvantage that all -- 5,000,000 pages using this module needed to be refreshed every time an image was added or removed. ]==] local p = {} -- determine whether we're being called from a sandbox local isSandbox = mw.getCurrentFrame():getTitle():find('sandbox', 1, true) local sandbox = isSandbox and '/sandbox' or '' local function sandboxVersion(s) return isSandbox and s..'-sand' or s end local templatestyles = 'Module:Portal'..sandbox..'/styles.css' local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') -- List of non-talk namespaces which should not be tracked (Talk pages are never tracked) local badNamespaces = {'user','template','draft','wikipedia'} -- Check whether to do tracking in this namespace -- Returns true unless the page is one of the banned namespaces local function checkTracking(title) local thisPage = title or mw.title.getCurrentTitle() if thisPage.isTalkPage then return false end local ns = thisPage.nsText:lower() for _, v in ipairs(badNamespaces) do if ns == v then return false end end return true end local function matchImagePage(s) -- Finds the appropriate image subpage given a lower-case -- portal name plus the first letter of that portal name. if type(s) ~= 'string' or #s < 1 then return end local firstLetter = mw.ustring.sub(s, 1, 1) local imagePage if mw.ustring.find(firstLetter, '^[a-z]') then imagePage = 'Module:Portal/images/' .. firstLetter .. sandbox else imagePage = 'Module:Portal/images/other' .. sandbox end return mw.loadData(imagePage)[s] end local function getAlias(s) -- Gets an alias from the image alias data page. local aliasData = mw.loadData('Module:Portal/images/aliases'..sandbox) for portal, aliases in pairs(aliasData) do for _, alias in ipairs(aliases) do if alias == s then return portal end end end end local function getImageName(s) -- Gets the image name for a given string. local default = 'Portal-puzzle.svg|link=|alt=' if type(s) ~= 'string' or #s < 1 then return default end s = mw.ustring.lower(s) return matchImagePage(s) or matchImagePage(getAlias(s)) or default end -- Function to check argument portals for errors, generate tracking categories if needed -- Function first checks for too few/many portals provided -- Then checks the portal list to purge any portals that don't exist -- Arguments: -- portals: raw list of portals -- args.tracking: is tracking requested? (will not track on bad titles or namespaces) -- args.redlinks: should redlinks be displayed? -- args.minPortals: minimum number of portal arguments -- args.maxPortals: maximum number of portal arguments -- Returns: -- portals = list of portals, with redlinks purged (if args.redlinks=false) -- trackingCat = possible tracking category -- errorMsg = error message function p._checkPortals(portals, args) local trackingCat = '' local errMsg = nil -- Tracking is on by default. -- It is disabled if any of the following is true -- 1/ the parameter "tracking" is set to 'no, 'n', or 'false' -- 2/ the current page fails the namespace or pagename tests local trackingEnabled = args.tracking and checkTracking() args.minPortals = args.minPortals or 1 args.maxPortals = args.maxPortals or -1 -- check for too few portals if #portals < args.minPortals then errMsg = 'please specify at least '..args.minPortals..' portal'..(args.minPortals > 1 and 's' or '') trackingCat = (trackingEnabled and '[[Category:Portal templates with too few portals]]' or '') return portals, trackingCat, errMsg end -- check for too many portals if args.maxPortals >= 0 and #portals > args.maxPortals then errMsg = 'too many portals (maximum = '..args.maxPortals..')' trackingCat = (trackingEnabled and '[[Category:Portal templates with too many portals]]' or '') return portals, trackingCat, errMsg end if not args.redlinks or trackingEnabled then -- make new list of portals that exist local existingPortals = {} for _, portal in ipairs(portals) do local portalTitle = mw.title.new(portal,"Portal") -- if portal exists, put it into list if portalTitle and portalTitle.exists then table.insert(existingPortals,portal) -- otherwise set tracking cat elseif trackingEnabled then trackingCat = "[[Category:Portal templates with redlinked portals]]" end end -- If redlinks is off, use portal list purged of redlinks portals = args.redlinks and portals or existingPortals -- if nothing left after purge, set tracking cat if #portals == 0 and trackingEnabled then trackingCat = trackingCat.."[[Category:Pages with empty portal template]]" end end return portals, trackingCat, errMsg end function p._portal(portals, args) -- This function builds the portal box used by the {{portal}} template. -- Normalize all arguments if args.redlinks == 'include' then args.redlinks = true end args.addBreak = args['break'] for key, default in pairs({left=false,tracking=true,nominimum=false, redlinks=false,addBreak=false,border=true}) do if args[key] == nil then args[key] = default end args[key] = yesno(args[key], default) end local root = mw.html.create('div') :attr('role', 'navigation') :attr('aria-label', 'Portals') :addClass('noprint plainlist') :addClass(sandboxVersion('portalbox')) :addClass(args.border and sandboxVersion('portalborder') or '') :addClass(args.left and 'tleft' or 'tright') :css('margin', args.margin or nil) :newline() local trackingCat = '' local errMsg = nil args.minPortals = args.nominimum and 0 or 1 args.maxPortals = -1 portals, trackingCat, errMsg = p._checkPortals(portals, args) root:wikitext(trackingCat) -- if error message, put it in the box and return if errMsg then if args.border then -- suppress error message when border=no local errTag = root:tag('strong') errTag:addClass('error') errTag:css('padding','0.2em') errTag:wikitext('Error: '..errMsg) end return tostring(root) end -- if no portals (and no error), just return tracking category if #portals == 0 then return trackingCat end -- Start the list. This corresponds to the start of the wikitext table in the old [[Template:Portal]]. local listroot = root:tag('ul') :css('width', (tonumber(args.boxsize) or 0) > 0 and (args.boxsize .. 'px') or args.boxsize) -- Display the portals specified in the positional arguments. for _, portal in ipairs(portals) do local image = getImageName(portal) -- Generate the html for the image and the portal name. listroot :newline() :tag('li') :tag('span') :wikitext(string.format('[[File:%s|32x28px|class=noviewer]]', image)) :done() :tag('span') :wikitext(string.format('[[Portal:%s|%s%sportal]]', portal, portal, args.addBreak and '<br />' or ' ')) end return tostring(root) end function p._image(portal,nostrip) -- Wrapper function to allow getImageName() to be accessed through #invoke. -- backward compatibility: if table passed, take first element if type(portal) == 'table' then portal = portal[1] end local name = getImageName(portal) -- If nostrip is yes (or equivalent), then allow all metadata (like image borders) to be returned local strip = not yesno(nostrip) return strip and name:match('^(.-)|') or name -- FIXME: use a more elegant way to separate borders etc. from the image name end local function getAllImageTables() -- Returns an array containing all image subpages (minus aliases) as loaded by mw.loadData. local images = {} for i, subpage in ipairs{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'other'} do images[i] = mw.loadData('Module:Portal/images/' .. subpage .. sandbox) end return images end function p._displayAll(portals, args) -- This function displays all portals that have portal images. This function is for maintenance purposes and should not be used in -- articles, for two reasons: 1) there are over 1500 portals with portal images, and 2) the module doesn't record how the portal -- names are capitalized, so the portal links may be broken. local lang = mw.language.getContentLanguage() local count = 1 for _, imageTable in ipairs(getAllImageTables()) do for portal in pairs(imageTable) do portals[count] = lang:ucfirst(portal) count = count + 1 end end return p._portal(portals, args) end function p._imageDupes() -- This function searches the image subpages to find duplicate images. If duplicate images exist, it is not necessarily a bad thing, -- as different portals might just happen to choose the same image. However, this function is helpful in identifying images that -- should be moved to a portal alias for ease of maintenance. local exists, dupes = {}, {} for _, imageTable in ipairs(getAllImageTables()) do for portal, image in pairs(imageTable) do if not exists[image] then exists[image] = portal else table.insert(dupes, string.format('The image "[[:File:%s|%s]]" is used for both portals "%s" and "%s".', image, image, exists[image], portal)) end end end if #dupes < 1 then return 'No duplicate images found.' else return 'The following duplicate images were found:\n* ' .. table.concat(dupes, '\n* ') end end local function processPortalArgs(args) -- This function processes a table of arguments and returns two tables: an array of portal names for processing by ipairs, and a table of -- the named arguments that specify style options, etc. We need to use ipairs because we want to list all the portals in the order -- they were passed to the template, but we also want to be able to deal with positional arguments passed explicitly, for example -- {{portal|2=Politics}}. The behaviour of ipairs is undefined if nil values are present, so we need to make sure they are all removed. args = type(args) == 'table' and args or {} local portals = {} local namedArgs = {} for k, v in pairs(args) do if type(k) == 'number' and type(v) == 'string' then -- Make sure we have no non-string portal names. table.insert(portals, k) elseif type(k) ~= 'number' then namedArgs[k] = v end end table.sort(portals) for i, v in ipairs(portals) do portals[i] = args[v] end return portals, namedArgs end -- Entry point for sorting portals from other named arguments function p._processPortalArgs(args) return processPortalArgs(args) end function p.image(frame) local origArgs = getArgs(frame) local portals, args = processPortalArgs(origArgs) return p._image(portals[1],args.border) end local function makeWrapper(funcName) -- Processes external arguments and sends them to the other functions. return function (frame) -- If called via #invoke, use the args passed into the invoking -- template, or the args passed to #invoke if any exist. Otherwise -- assume args are being passed directly in from the debug console -- or from another Lua module. -- Also: trim whitespace and remove blank arguments local origArgs = getArgs(frame) -- create two tables to pass to func: an array of portal names, and a table of named arguments. local portals, args = processPortalArgs(origArgs) local results = '' if funcName == '_portal' or funcName == '_displayAll' then results = frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles} } end return results .. p[funcName](portals, args) end end for _, funcName in ipairs{'portal', 'imageDupes', 'displayAll'} do p[funcName] = makeWrapper('_' .. funcName) end return p 078bc1925b1a76f62f668379257fd789d6d85d4b Template:Reflist 10 87 189 2022-06-11T17:42:16Z Canopus >Izno 0 correct my error per [[Template talk:Reflist#liststyle and group]] wikitext text/x-wiki <templatestyles src="Reflist/styles.css" /><div class="reflist <!-- -->{{#if:{{{1|}}}{{{colwidth|}}}|reflist-columns references-column-width}} <!-- -->{{#switch:{{{liststyle|{{{group|}}}}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=reflist-{{{liststyle|{{{group}}}}}}}} <!-- -->{{#if:{{{1|}}}|{{#iferror:{{#ifexpr: {{{1|1}}} > 1 }}||{{#switch:{{{1|}}}|1=|2=reflist-columns-2|#default=reflist-columns-3}} }}}}" <!-- end class -->{{#if: {{{1|}}}<!-- start style --> | {{#iferror: {{#ifexpr: {{{1|1}}} > 1 }} |style="column-width: {{{1}}};"}} | {{#if: {{{colwidth|}}}|style="column-width: {{{colwidth}}};"}} }}> {{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive={{#if:{{{1|}}}{{{colwidth|}}}|0|1}}}}</div>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using reflist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Reflist]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | colwidth | group | liststyle | refs }}<noinclude> {{Documentation}} </noinclude> 8c65cc88272db6c0f5cf2b49f84d3e460e60ee5f Template:Clear 10 89 193 2022-06-13T15:31:11Z Canopus >Xaosflux 0 Changed protection settings for "[[Template:Clear]]": [[WP:High-risk templates|Highly visible template]]: 3MM+ uses ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite)) wikitext text/x-wiki <div style="clear:{{{1|both}}};"></div><noinclude> {{documentation}} </noinclude> 38bab3e3d7fbd3d6800d46556e60bc6bac494d72 Module:Portal/images/s 828 86 187 2022-06-13T17:21:18Z Canopus >Nihonjoe 0 typo Scribunto text/plain --[==[ This is the "S" list of portal image names. It contains a list of portal images for use with [[Module:Portal]] -- for portal names that start with the letter "S". For aliases to existing portal names, and for portal names that -- start with other letters, please use the appropriate page from the following list: -- [[Module:Portal/images/a]] - for portal names beginning with "A". -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/o]] - for portal names beginning with "O". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- [[Module:Portal/images/aliases]] - for adding aliases for existing portal names. Use this page for variations -- in spelling and diacritics, etc., no matter what letter the portal begins with. -- When adding entries, please use alphabetical order. The format of the images table entries is as follows: -- ["portal name"] = "image.svg", -- The portal name should be the name of your portal, in lower case. For example, the portal name for -- "Portal:United Kingdom" would be "united kingdom". The image name should be capitalised normally, and the "File:" -- namespace prefix should be omitted. ]==] return { ["saarc"] = "SAARC 1717549468.png|link=|alt=icon", ["saarland"] = "Flag of Saarland.svg|border|link=|alt=flag", ["saba"] = "Flag of Saba.svg|border|link=|alt=flag", ["sabah"] = "Flag of Sabah.svg|border|link=|alt=flag", ["sacred christian music"] = "Musical note nicu bucule 01.svg|link=|alt=icon", ["saguenay–lac-saint-jean"] = "Flag of Saguenay-Lac-Saint-Jean.svg|border|link=|alt=flag", ["sailing"] = "Sailing pictogram.svg|link=|alt=", ["saint barthelemy"] = "Flag of Saint Barthelemy (local).svg|border|link=|alt=flag", ["saint helena, ascension and tristan da cunha"] = "Flag of Saint Helena.svg|border|link=|alt=flag", ["saint kitts and nevis"] = "Flag of Saint Kitts and Nevis.svg|border|link=|alt=flag", ["saint lucia"] = "Flag of Saint Lucia.svg|border|link=|alt=flag", ["saint martin"] = "Flag of Saint Martin.png|border|link=|alt=flag", ["saint petersburg"] = "Flag of Saint Petersburg Russia.svg|alt=flag", ["saint pierre and miquelon"] = "Flag of Saint-Pierre and Miquelon.svg|border|link=|alt=flag", ["saint vincent and the grenadines"] = "Flag of Saint Vincent and the Grenadines.svg|border|link=|alt=flag", ["saints"] = "Gloriole blur.svg|link=|alt=", ["salad dressing"] = "Ranch dressing.jpg|link=|alt=", ["salmon"] = "Alaska salmon.jpg|link=|alt=", ["samoa"] = "Flag of Samoa.svg|border|link=|alt=flag", ["san antonio"] = "Coat of arms of San Antonio.svg|link=|alt=arms", ["san diego"] = "San Diego,California,USA. - panoramio (139).jpg|link=|alt=photo", ["san diego county"] = "Seal of San Diego County, California.png|link=|alt=seal", ["san diego–tijuana"] = "San Diego-Tijuana JPLLandsat.jpg|border|link=|alt=flag", ["sandwich"] = "Sandwich (1).jpg|link=|alt=", ["san francisco bay area"] = "SF From Marin Highlands3.jpg|border|link=|alt=", ["san francisco neighborhoods"] = "Columbus and Broadway (8219737166).jpg|link=|alt=", ["san luis potosí"] = "Flag of San Luis Potosi.svg|border|link=|alt=flag", ["san marino"] = "Flag of San Marino.svg|border|link=|alt=flag", ["santa barbara county"] = "Seal of Santa Barbara County, California.png|link=|alt=seal", ["santana"] = "Carlos Santana 2005.jpg|link=|alt=", ["santiago, chile"] = "Flag of Santiago de Chile.svg|alt=flag", ["são tomé and príncipe"] = "Flag of Sao Tome and Principe.svg|border|link=|alt=flag", ["são paulo"] = "Bandeira da cidade de São Paulo.svg|link=|alt=", ["salad"] = "Composed salad.jpg|link=|alt=", ["salads"] = "Composed salad.jpg|link=|alt=", ["salt"] = "Keukenzout (NaCl), onder de microscoop.jpg|link=|alt=", ["santiago"] = "Flag of Santiago de Chile.svg|alt=flag", ["sarajevo"] = "Flag of Sarajevo.svg|alt=flag", ["sarawak"] = "Flag of Sarawak.svg|border|link=|alt=flag", ["sasanian empire"] = "Derafsh Kaviani flag of the late Sassanid Empire.svg|border|link=|alt=flag", ["saskatchewan"] = "Flag of Saskatchewan.svg|border|link=|alt=flag", ["saskatchewan communities and neighbourhoods"] = "Flag-map of Saskatchewan.svg|link=|alt=map", ["saturn"] = "Saturn - April 25 2016 (24102807868).png|link=|alt=", ["saudi arabia"] = "Flag of Saudi Arabia.svg|border|link=|alt=flag", ["sausage"] = "Saucisses.svg|link=|alt=", ["sausages"] = "Saucisses.svg|link=|alt=", ["saxony"] = "Flag of Saxony.svg|border|link=|alt=flag", ["saxony-anhalt"] = "Flag of Saxony-Anhalt (state).svg|border|link=|alt=flag", ["schleswig-holstein"] = "Flag of Schleswig-Holstein (state).svg|border|link=|alt=flag", ["schools"] = "School.svg|link=|alt=icon", ["science"] = "Nuvola apps kalzium.svg|alt=icon", ["science and academia"] = "Rachel Carson w (cropped).jpg|link=|alt=photo", ["science fiction"] = "Sf-userbox.png|alt=icon", ["scientology"] = "Scientology e meter blue.jpg|alt=icon", ["scifi"] = "Sf-userbox.png|alt=icon", ["scotland"] = "Flag of Scotland.svg|border|link=|alt=flag", ["scottish islands"] = "ScottishIsles.jpg|link=|alt=map", ["scouting"] = "WikiProject Scouting fleur-de-lis dark.svg|alt=icon", ["sculpture"] = "Noun Project - Sculpture.svg|alt=", ["seafood"] = "Crab-icon.png|link=|alt=", ["seamounts"] = "Seamount.svg|link=|alt=", ["seattle"] = "SpaceNeedleTopClose.jpg|alt=icon", ["sega"] = "SEGA logo.svg|link=|alt=", ["senegal"] = "Flag of Senegal.svg|border|link=|alt=flag", ["selangor"] = "Flag of Selangor.svg|alt=flag", ["seoul"] = "Seal of Seoul.svg|link=|alt=seal", ["september 11 attacks"] = "Y24-Wtc-september-5.jpg|alt=icon", ["serbia"] = "Flag of Serbia.svg|border|link=|alt=flag", ["serbian cuisine"] = "Ćevapčići.jpg|link=|alt=", ["serer people"] = "Serer Royal War Drum (Jung-Jung). 19th Century. Jung-Jung From The Kingdom of Sine (in modern day Senegal).jpg|alt=icon", ["serer religion"] = "Five Pointed Star Lined.svg|link=|alt=", ["set theory"] = "Venn0001.svg|link=|alt=", ["seton hall university"] = "Shu logo.png|link=|alt=logo", ["seventh-day adventist church"] = "James and Ellen White.jpg|link=|alt=", ["severe weather"] = "Marquette, Kansas EF4 tornado on April 14, 2012.png|link=|alt=icon", ["sexuality"] = "Bisexuality symbol (bold, color).svg|alt=icon", ["sex work"] = "Umbrella-159361.svg|link=|alt=", ["seychelles"] = "Flag of Seychelles.svg|border|link=|alt=flag", ["sf"] = "Dragon-149393.svg|alt=icon", ["sfpeople"] = "Dragon-149393.svg|alt=icon", ["sfpubs"] = "Dragon-149393.svg|alt=icon", ["shakespeare"] = "Shakespeare (oval-cropped).png|link=|alt=", ["shakira"] = "S by shakira logo.png|alt=icon", ["shanghai"] = "Shanghainame.png|link=|alt=", ["shania twain"] = "Shania Twain Portrait.jpg|alt=icon", ["sharjah"] = "Flag of Sharjah.svg|border|link=|alt=flag", ["sharks"] = "Greyreefsharksmall2.jpg|alt=icon", ["shenzhen"] = "Shenzhen in Chinese.png|alt=Shenzhen", ["shia islam"] = "Ghadir logo.png|alt=icon", ["shinto"] = "Shinto torii icon vermillion.svg|link=|alt=", ["shreveport"] = "Shreveport-City-Flag.png|border|link=|alt=flag", ["shreya ghoshal"] = "Shreya at concert.jpg|alt=icon", ["shropshire"] = "Flag of Shropshire.svg|alt=flag|link=", ["siberia"] = "Kuznetsk Alatau 3.jpg|border|link=|alt=", ["sierra leone"] = "Flag of Sierra Leone.svg|border|link=|alt=flag", ["sikhism"] = "Khanda emblem.svg|link=|alt=", ["sikkim"] = "Seal of Sikkim color.png|link=|alt=seal", ["silent film"] = "Video-x-generic.svg|link=|alt=", ["silesia"] = "Silesia Inferior COA.svg|alt=icon", ["sinaloa"] = "Flag of Sinaloa.svg|border|link=|alt=flag", ["sindh"] = "Flag of Sindh.svg|border|link=|alt=flag", ["singapore"] = "Flag of Singapore.svg|border|link=|alt=flag", ["sint eustatius"] = "Flag of Sint Eustatius.svg|border|link=|alt=flag", ["sint maarten"] = "Flag of Sint Maarten.svg|border|link=|alt=flag", ["slavery"] = "IJzeren voetring voor gevangenen transparent background.png|border|link=|alt=icon", ["slipknot"] = "SlipknotProject.png|alt=icon", ["slovak republic"] = "Flag of Slovakia.svg|border|link=|alt=flag", ["slovakia"] = "Flag of Slovakia.svg|border|link=|alt=flag", ["slovenia"] = "Flag of Slovenia.svg|border|link=|alt=flag", ["sm entertainment"] = "SM Entertainment Logo.svg|link=|alt=", ["snakes"] = "Snake icon.svg|link=|alt=", ["snk"] = "SNK Playmore logo and wordmark.png|link=|alt=", ["snooker"] = "Snooker balls triangled.png|alt=icon", ["soap operas and telenovelas"] = "Drama-icon.svg|alt=icon", ["soccer in the united states"] = "Soccerball USA.png|link=|alt=", ["social and political philosophy"] = "P derecho.svg|link=|alt=", ["social movements"] = "Peace sign.svg|link=|alt=", ["social science"] = "P social sciences-lightblue.png|link=|alt=icon", ["social sciences"] = "DrustveneNauke.png|alt=icon", ["social welfare and social work"] = "Vista Login Manager Cropped.svg|alt=icon", ["socialism"] = "Red flag II.svg|alt=icon", ["society"] = "Social sciences.svg|alt=icon", ["sociology"] = "Logo sociology.svg|link=|alt=", ["soft drinks"] = "Soft Drink.svg|link=|alt=", ["software"] = "Crystal Clear device cdrom unmount.png|alt=icon", ["software testing"] = "Green bug and broom.svg|alt=icon", ["solar system"] = "Solar system.jpg|link=|alt=", ["solomon islands"] = "Flag of Solomon Islands.svg|border|link=|alt=flag", ["somalia"] = "Flag of Somalia.svg|border|link=|alt=flag", ["somaliland"] = "Flag of Somaliland.svg|border|link=|alt=flag", ["somerset"] = "Somerset shield.png|alt=icon", ["sonic"] = "Chaos emeralds.svg|alt=icon", ["sonora"] = "Flag of Sonora.svg|border|link=|alt=flag", ["sony"] = "Sony logo.svg|link=|alt=", ["sony playstation"] = "PS3-slim-console.png|link=|alt=", ["soup"] = "Shrimp and corn chowder.jpg|link=|alt=", ["soups"] = "Shrimp and corn chowder.jpg|link=|alt=", ["south africa"] = "Flag of South Africa.svg|border|link=|alt=flag", ["south america"] = "South America (orthographic projection).svg|link=|alt=map", ["south asia"] = "India 78.40398E 20.74980N.jpg|link=|alt=", ["south australia"] = "Flag of South Australia.svg|border|link=|alt=flag", ["south carolina"] = "Flag of South Carolina.svg|border|link=|alt=flag", ["south dakota"] = "Flag of South Dakota.svg|border|link=|alt=flag", ["south east england"] = "EnglandSouthEast.png|alt=icon", ["south georgia and the south sandwich islands"] = "Flag of South Georgia and the South Sandwich Islands.svg|border|link=|alt=flag", ["south korea"] = "Flag of South Korea.svg|border|link=|alt=flag", ["south park"] = "South Park sign logo.png|link=|alt=", ["south sudan"] = "Flag of South Sudan.svg|border|link=|alt=flag", ["southeast asia"] = "Location Southeast Asia.svg|link=|alt=", ["southern california"] = "USA California Southern location map.svg|link=|alt=map", ["southwest asia"] = "Southwest-Asia-map.PNG|link=|alt=", ["soviet union"] = "Flag of the Soviet Union.svg|border|link=|alt=flag", ["soy"] = "CSIRO ScienceImage 3273 Soybeans.jpg|link=|alt=", ["space"] = "Earth-moon.jpg|link=|alt=", ["spaceflight"] = "RocketSunIcon.svg|link=|alt=", ["spain"] = "Flag of Spain.svg|border|link=|alt=flag", ["spanish american wars of independence"] = "Red versus blue swords.svg|alt=icon", ["special operations"] = "APP-6 Special Operations Forces.svg|link=|alt=", ["speculative fiction"] = "Dragon-149393.svg|alt=icon", ["speculative fiction/fantasy"] = "Masked man.svg|link=|alt=icon", ["speculative fiction/horror"] = "Vampire Smiley.png|alt=icon", ["speculative fiction/people"] = "Dragon-149393.svg|alt=icon", ["speculative fiction/publications"] = "Dragon-149393.svg|alt=icon", ["spices"] = "Thymus vulgaris.jpg|link=|alt=icon", ["spirituality"] = "EndlessKnot03d.png|link=|alt=", ["spongebob squarepants"] = "WikiProject SpongeBob logo - Logo.svg|alt=icon", ["sports"] = "Sports icon.png|link=|alt=", ["sports and games"] = "Sports and games.png|alt=icon", ["sports in canada"] = "Flag shirt of Canada.png|alt=icon", ["sport of athletics"] = "Roman bronze copy of Myron’s Discobolos, 2nd century CE (Glyptothek Munich).jpg|link=|alt=", ["sri lanka"] = "Flag of Sri Lanka.svg|border|link=|alt=flag", ["sri lankan cuisine"] = "Kiribath (milk rice).jpg|link=|alt=", ["st. john's, newfoundland and labrador"] = "City of St. John's.jpg|link=|alt=", ["st. louis"] = "Flag of St. Louis, Missouri.svg|border|link=|alt=flag", ["staffordshire"] = "Staffordshire Flag.svg|border|link=|alt=flag", ["stamford"] = "Stamford town crest.png|link=|alt=crest", ["stanford university"] = "Stanford logo.png|link=|alt=logo", ["star"] = "He1523a.jpg|alt=icon", ["stars"] = "He1523a.jpg|alt=icon", ["star trek"] = "Delta-shield.svg|link=|alt=", ["star wars"] = "Lightsaber blue.svg|link=|alt=", ["state of georgia"] = "Flag of Georgia (U.S. state).svg|border|link=|alt=flag", ["state of mexico"] = "Flag of Mexico (state).png|border|link=|alt=flag", ["state university of new york"] = "SUNY brandmark.svg|link=|alt=brandmark", ["state university system of florida"] = "SUSF Locations.jpg|link=|alt=map", ["statistics"] = "Fisher iris versicolor sepalwidth.svg|alt=icon", ["statue of liberty"] = "FREEDOM FOR ALL!.jpg|alt=", ["steampunk"] = "Steampunk-falksen.jpg|alt=icon", ["stockholm"] = "Flag of Stockholm.svg|alt=flag", ["strategy games"] = "Chess.svg|alt=icon", ["strawberries"] = "FraiseFruitPhoto.jpg|link=|alt=", ["strawberry"] = "FraiseFruitPhoto.jpg|link=|alt=", ["street food"] = "Food Truck - The Noun Project.svg|link=|alt=", ["street foods"] = "Food Truck - The Noun Project.svg|link=|alt=", ["submarine"] = "Submarine.svg|alt=icon", ["submarines"] = "Submarine.svg|alt=icon", ["sudan"] = "Flag of Sudan.svg|border|link=|alt=flag", ["sufism"] = "Soefi symbool.gif|link=|alt=", ["super bowl"] = "Lombardi Trophy.png|link=|alt=", ["superfunds"] = "Superfund sites.svg|link=|alt=map", ["superhero fiction"] = "Question bubble thing.svg|link=|alt=", ["supermarket"] = "ShoppingCart.svg|link=|alt=", ["supermarkets"] = "ShoppingCart.svg|link=|alt=", ["supreme court of the united states"] = "Supreme Court.jpg|link=|alt=", ["surat"] = "Surat at night.JPG|link=|alt=photo", ["surfing"] = "Pictograms-nps-water-surfing.svg|link=|alt=", ["suriname"] = "Flag of Suriname.svg|border|link=|alt=flag", ["surrey"] = "EnglandSurrey.png|alt=icon", ["sushi"] = "Emojione 1F363.svg|border|link=|alt=", ["sustainability"] = "Nested sustainability-v2.svg|border|link=|alt=", ["sussex"] = "SussexBrit5.PNG|link=|alt=", ["sustainable development"] = "Sustainable development.svg|alt=icon", ["sweden"] = "Flag of Sweden.svg|border|link=|alt=flag", ["swimming"] = "Swimming pictogram.svg|link=|alt=", ["switzerland"] = "Flag of Switzerland.svg|border|link=|alt=flag", ["sydney"] = "Sydney COA.gif|alt=icon", ["syracuse, new york"] = "SyracuseSkyline01.JPG|link=|alt=", ["syria"] = "Flag of Syria.svg|border|link=|alt=flag", ["syriac christianity"] = "Bible and Pulpit, Mor Hananyo.jpg|alt=icon", ["syriac"] = "Syriac Sertâ book script.jpg|link=|alt=", ["syrian civil war"] = "Flag of Syria (2011 combined).svg|border|link=|alt=flag", ["systems"] = "Complex-adaptive-system.jpg|link=|alt=diagram", ["systems engineering initiative"] = "Systems Engineering Process II.gif|link=|alt=diagram", ["systems science"] = "Complex-adaptive-system.jpg|link=|alt=diagram" } a240880fd11e77e94cd6091361c41c9fdf8e85df Template:Starbox detail 10 156 327 2022-06-15T13:02:40Z Canopus >Primefac 0 tweak to avoid false positives wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><th style="background-color: #FFFFC0; text-align: center;" colspan="2">{{#if:{{{no_heading|}}}||Details{{{source|}}}}}</th></tr>{{#if:{{{component|}}}|<tr style="text-align:center"><th colspan="2">{{{component}}}</th></tr>}}</th></tr><!-- --><tr><th colspan="2" style="text-align: center">{{{component1<includeonly>|</includeonly>}}}</th></tr><!-- -->{{#if:{{{mass<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar mass|Mass]]'''</td><td>{{{mass}}}&nbsp;{{Solar mass|link=yes}}</td></tr>}}<!-- -->{{#if:{{{mass_mj<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar mass|Mass]]'''</td><td>{{{mass_mj}}}&nbsp;[[Jupiter mass|''M''<sub>Jup</sub>]]</td></tr>}}<!-- -->{{#if:{{{radius<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius}}}&nbsp;{{Solar radius|link=yes}}</td></tr>}}<!-- -->{{#if:{{{radius_rj<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius_rj}}}&nbsp;[[Jupiter radius|''R''<sub>Jup</sub>]]</td></tr>}}<!-- -->{{#if:{{{radius_km<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius_km}}}&nbsp;[[kilometer|km]]</td></tr>}}<!-- -->{{#if:{{{luminosity<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Luminosity]]'''</td><td>{{{luminosity}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{luminosity_bolometric<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity (bolometric)'''</td><td>{{{luminosity_bolometric}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{luminosity_visual<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity (visual, L<sub>V</sub>)'''</td><td>{{{luminosity_visual}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{habitable_inner<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline:"><td>'''[[Habitable zone]] inner limit'''</td><td>{{{habitable_inner}}}</td></tr>}}<!-- -->{{#if:{{{habitable_outer<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline:"><td>'''[[Habitable zone]] outer limit'''</td><td>{{{habitable_outer}}}</td></tr>}}<!-- -->{{#if:{{{gravity<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Surface gravity]] (log&nbsp;''g'')'''</td><td>{{{gravity}}}&nbsp;[[Centimetre–gram–second system of units|cgs]]</td></tr>}}<!-- -->{{#if:{{{temperature<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Effective temperature|Temperature]]'''</td><td>{{{temperature}}}&nbsp;[[Kelvin|K]]</td></tr>}}<!-- -->{{#if:{{{metal<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Metallicity]]'''</td><td>{{{metal}}}</td></tr>}}<!-- -->{{#if:{{{metal_fe<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Metallicity]]''' [Fe/H]</td><td>{{{metal_fe}}}&nbsp;[[Decimal exponent|dex]]</td></tr>}}<!-- -->{{#if:{{{rotation<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar rotation|Rotation]]'''</td><td>{{{rotation}}}</td></tr>}}<!-- -->{{#if:{{{rotational_velocity<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Projected rotational velocity|Rotational velocity]] (''v''&nbsp;sin&nbsp;''i'')'''</td><td>{{{rotational_velocity}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{age<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar evolution|Age]]'''</td><td>{{{age}}}&nbsp;years</td></tr>}}<!-- -->{{#if:{{{age_myr<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>{{#if:{{{age|}}}|&nbsp;|'''[[Stellar evolution|Age]]'''}}</td><td>{{{age_myr}}}&nbsp;[[megayear|Myr]]</td></tr>}}<!-- -->{{#if:{{{age_gyr<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>{{#if:{{{age|}}}|&nbsp;|'''[[Stellar evolution|Age]]'''}}</td><td>{{{age_gyr}}}&nbsp;[[gigayear|Gyr]]</td></tr>}}<!-- --><tr><th colspan="2" style="text-align: center">{{{component2<includeonly>|</includeonly>}}}</th></tr><!-- -->{{#if:{{{mass2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar mass|Mass]]'''</td><td>{{{mass2}}}&nbsp;{{Solar mass|link=yes}}</td></tr>}}<!-- -->{{#if:{{{mass_mj2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar mass|Mass]]'''</td><td>{{{mass_mj2}}}&nbsp;[[Jupiter mass|''M''<sub>Jup</sub>]]</td></tr>}}<!-- -->{{#if:{{{radius2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius2}}}&nbsp;{{Solar radius|link=yes}}</td></tr>}}<!-- -->{{#if:{{{radius_rj2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius_rj2}}}&nbsp;[[Jupiter radius|''R''<sub>Jup</sub>]]</td></tr>}}<!-- -->{{#if:{{{radius_km2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius_km2}}}&nbsp;[[kilometer|km]]</td></tr>}}<!-- -->{{#if:{{{luminosity2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity'''</td><td>{{{luminosity2}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{luminosity_bolometric2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity (bolometric)'''</td><td>{{{luminosity_bolometric2}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{luminosity_visual2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity (visual, L<sub>V</sub>)'''</td><td>{{{luminosity_visual2}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{habitable_inner2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline:"><td>'''[[Habitable zone]] inner limit'''</td><td>{{{habitable_inner2}}}</td></tr>}}<!-- -->{{#if:{{{habitable_outer2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline:"><td>'''[[Habitable zone]] outer limit'''</td><td>{{{habitable_outer2}}}</td></tr>}}<!-- -->{{#if:{{{gravity2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Surface gravity]] (log&nbsp;''g'')'''</td><td>{{{gravity2}}}&nbsp;[[Centimetre–gram–second system of units|cgs]]</td></tr>}}<!-- -->{{#if:{{{temperature2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Effective temperature|Temperature]]'''</td><td>{{{temperature2}}}&nbsp;[[Kelvin|K]]</td></tr>}}<!-- -->{{#if:{{{metal2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Metallicity]]'''</td><td>{{{metal2}}}</td></tr>}}<!-- -->{{#if:{{if empty|{{{metal_fe2|}}}|{{{metal2_fe|}}}|<noinclude>x</noinclude>}}|<tr style="vertical-align:baseline;"><td>'''[[Metallicity]]''' [Fe/H]</td><td>{{{metal2_fe|{{{metal_fe2}}}}}}&nbsp;[[Decimal exponent|dex]]</td></tr>}}<!-- -->{{#if:{{{rotation2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar rotation|Rotation]]'''</td><td>{{{rotation2}}}</td></tr>}}<!-- -->{{#if:{{{rotational_velocity2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Projected rotational velocity|Rotational velocity]] (''v''&nbsp;sin&nbsp;''i'')'''</td><td>{{{rotational_velocity2}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{age2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Star#Age_and_size_of_stars|Age]]'''</td><td>{{{age2}}}&nbsp;years</td></tr>}}<!-- -->{{#if:{{{age_myr2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>{{#if:{{{age2|}}}|&nbsp;|'''[[Star#Age_and_size_of_stars|Age]]'''}}</td><td>{{{age_myr2}}}&nbsp;[[megayear|Myr]]</td></tr>}}<!-- -->{{#if:{{{age_gyr2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>{{#if:{{{age2|}}}|&nbsp;|'''[[Star#Age_and_size_of_stars|Age]]'''}}</td><td>{{{age_gyr2}}}&nbsp;[[gigayear|Gyr]]</td></tr>}}<noinclude> |} <!-- Please add categories to the /doc subpage; interwikis go to Wikidata, thank you! --> {{Documentation}} </noinclude> 7f2d91f20c11e77a3a015d033ec4771978d97588 Template:Carina (constellation) 10 161 337 2022-06-15T14:50:36Z Canopus >RL0919 0 Removing link(s) [[Wikipedia:Articles for deletion/LEDA 2791735]] closed as delete ([[WP:XFDC#4.0.13|XFDcloser]]) wikitext text/x-wiki {{Navbox | name = Carina (constellation) | title = [[Carina (constellation)|Carina constellation]] | bodyclass = hlist | state = {{{state|<noinclude>uncollapsed</noinclude>}}} | group1 = [[Star]]s<br>([[List of stars in Carina|list]]) | list1 = {{Navbox|subgroup | group1 = [[Bayer designation|Bayer]] | list1 = * [[Canopus|α (Canopus)]] * [[Beta Carinae|β (Miaplacidus)]] * [[Epsilon Carinae|ε (Avior)]] * [[Eta Carinae|η]] * [[Theta Carinae|θ]] * [[Iota Carinae|ι (Aspidiske)]] * [[Upsilon Carinae|υ]] * [[Chi Carinae|χ]] * [[Omega Carinae|ω]] | group3 = [[Variable star designation|Variable]] | list3 = * [[R Carinae|R]] * [[HD 88366|S]] * [[T Carinae|T (not variable)]] * [[HD 95109|U]] * [[V Carinae|V]] * [[X Carinae|X]] * [[Y Carinae|Y]] * [[RT Carinae|RT]] * [[UX Carinae|UX]] * [[VY Carinae|VY]] * [[WZ Carinae|WZ]] * [[XY Carinae|XY]] * [[XZ Carinae|XZ]] * [[YZ Carinae|YZ]] * [[AG Carinae|AG]] * [[BO Carinae|BO]] * [[CK Carinae|CK]] * [[CR Carinae|CR]] * [[DW Carinae|DW]] * [[EM Carinae|EM]] * [[EY Carinae|EY]] * [[GG Carinae|GG]] * [[GH Carinae|GH]] * [[GL Carinae|GL]] * [[GZ Carinae|GZ]] * [[HH Carinae|HH]] * [[HR Carinae|HR]] * [[IW Carinae|IW]] * [[IX Carinae|IX]] * [[OY Carinae|OY]] * [[PP Carinae|PP (p)]] * [[QU Carinae|QU]] * [[QX Carinae|QX]] * [[HD 88661|QY]] * [[QZ Carinae|QZ]] * [[V337 Carinae|V337 (q)]] * [[HD 65750|V341]] * [[V343 Carinae|V343 (d)]] * [[V344 Carinae|V344 (f)]] * [[V345 Carinae|V345 (E)]] * [[V348 Carinae|V348]] * [[V357 Carinae|V357 (a)]] * [[HD 92664|V364]] * [[V368 Carinae|V368]] * [[HD 91619|V369]] * [[HD 92207|V370]] * [[HD 96919|V371 (z<sup>2</sup>)]] * [[V372 Carinae|V372]] * [[HD 66194|V374]] * [[V375 Carinae|V375]] * [[V376 Carinae|V376 (b<sup>1</sup>)]] * [[HD 92024|V381]] * [[V382 Carinae|V382 (x)]] * [[V386 Carinae|V386]] * [[V390 Carinae|V390]] * [[V392 Carinae|V392]] * [[HD 90657|V398]] * [[V399 Carinae|V399 (P)]] * [[V403 Carinae|V403]] * [[HD 60435|V409]] * [[HD 96248|V414]] * [[HR 2554|V415 (A)]] * [[HD 94546|V428]] * [[HD 96446|V430]] * [[HD 97152|V431]] * [[V448 Carinae|V448 (O)]] * [[V450 Carinae|V450]] * [[HR 3153|V460]] * [[V461 Carinae|V461]] * [[V469 Carinae|V469]] * [[V473 Carinae|V473]] * [[V478 Carinae|V478]] * [[V482 Carinae|V482]] * [[V486 Carinae|V486]] * [[V487 Carinae|V487]] * [[V492 Carinae|V492]] * [[V495 Carinae|V495]] * [[V507 Carinae|V507]] * [[V514 Carinae|V514]] * [[V518 Carinae|V518]] * [[HD 92964|V519]] * [[V520 Carinae|V520 (w)]] * [[V522 Carinae|V522]] * [[V524 Carinae|V524]] * [[V528 Carinae|V528]] * [[V532 Carinae|V532]] * [[V533 Carinae|V533 (y)]] * [[V535 Carinae|V535]] * [[HD 307938|V557]] * [[HD 93205|V560]] * [[HD 85567|V596]] * [[HD 87643|V640]] * [[V655 Carinae|V655]] * [[V906 Carinae|V906]] | group4 = [[Bright Star Catalogue|HR]] | list4 = * [[HD 44267|2278]] * [[HD 46569|2400]] * [[HD 47001|2416]] * [[N Carinae|2435 (N)]] * [[HD 49517|2515]] * [[HD 49689|2523]] * [[HD 49705|2524]] * [[HD 51210|2592]] * [[HD 52603|2634]] * [[HD 52622|2638]] * [[HD 53047|2652]] * [[HD 53349|2661]] * [[HD 54732|2698]] * [[HD 56239|2754]] * [[HD 56705|2767]] * [[HD 57852|2813]] * [[HD 57917|2815]] * [[HD 59219|2862]] * [[HD 60060|2884]] * [[HD 60228|2892]] * [[HD 61031|2925]] * [[HD 61248|2934 (Q)]] * [[HD 61394|2941]] * [[HD 62758|3006]] * [[HD 62897|3012]] * [[HD 63382|3031]] * [[HD 63926|3056]] * [[HD 64067|3062]] * [[HD 64185|3070]] * [[HD 65189|3100]] * [[HD 65273|3105]] * [[HD 65662|3120]] * [[HD 65867|3133]] * [[HD 65907|3138]] * [[HD 65908|3139]] * [[HD 66341|3152]] * [[HD 66441|3156]] * [[HR 3159|3159 (D)]] * [[HD 66607|3161]] * [[HD 67364|3180]] * [[HD 68423|3217]] * [[HD 68434|3218]] * [[HR 3220|3220 (B)]] * [[HD 69863|3260 (C)]] * [[HD 70267|3274]] * [[HD 70839|3293]] * [[HD 70982|3298]] * [[HD 72322|3368]] * [[HD 73389|3414 (e<sup>2</sup>)]] * [[HD 73390|3415 (e<sup>1</sup>)]] * [[HD 73887|3432]] * [[HD 74148|3443]] * [[HD 74341|3455]] * [[HD 74622|3471]] * [[HD 75086|3489]] * [[HD 76113|3536]] * [[HD 76346|3549]] * [[HD 76538|3560]] * [[HD 76728|3571 (c)]] * [[HD 77370|3598 (b<sup>2</sup>)]] * [[HD 77615|3604]] * [[HD 78293|3622]] * [[HD 78632|3632]] * [[HR 3643|3643 (G)]] * [[HD 79447|3663 (i)]] * [[HD 79698|3673]] * [[HD 80094|3691]] * [[HD 80126|3693]] * [[HD 80230|3696 (g)]] * [[HD 80671|3712]] * [[HD 80951|3720]] * [[HD 80950|3721]] * [[HD 81101|3728 (k)]] * [[HD 81502|3740]] * [[HD 81613|3742]] * [[HD 81830|3752]] * [[HD 82068|3761]] * [[HD 82347|3776]] * [[HD 82350|3777]] * [[HD 82406|3783]] * [[HD 82858|3813]] * [[HD 83095|3821 (H)]] * [[HD 83183|3825 (h)]] * [[HD 83944|3856 (m)]] * [[HD 84121|3863]] * [[HD 84152|3864]] * [[HD 84810|3884 (l)]] * [[HD 84850|3887]] * [[HD 85655|3913]] * [[HD 85656|3914]] * [[HD 86606|3944]] * [[HD 87238|3957]] * [[HD 87283|3960]] * [[HD 87436|3966]] * [[HD 87438|3967]] * [[HD 87543|3971]] * [[HD 88323|3995]] * [[HD 88473|4002]] * [[HD 88825|4018]] * [[HD 88907|4022]] * [[HD 88981|4025 (M)]] * [[HD 89263|4043]] * [[HD 89715|4065]] * [[HD 90264|4089 (L)]] * [[HD 90289|4091]] * [[HD 90454|4095]] * [[HR 4102|4102 (I)]] * [[HD 90630|4105]] * [[HD 90853|4114 (s)]] * [[HD 90874|4115]] * [[HD 91056|4120]] * [[HD 91270|4128]] * [[HR 4138|4138 (K)]] * [[HD 91496|4142]] * [[HD 91533|4144]] * [[HD 91767|4151]] * [[HD 91942|4159 (r)]] * [[HD 92063|4164 (t<sup>1</sup>)]] * [[HD 92397|4177 (t<sup>2</sup>)]] * [[HD 92436|4179]] * [[HD 92682|4186]] * [[HD 93163|4204]] * [[HD 93194|4205]] * [[HD 93344|4211]] * [[HD 93359|4212]] * [[HD 93372|V213]] * [[HD 93502|4217]] * [[HD 93540|4219]] * [[HD 93549|4220]] * [[HD 93607|4222]] * [[HD 93662|4226]] * [[HD 93943|4239]] * [[HD 94510|4257 (u)]] * [[HD 94650|4262]] <!--Search the HR number on SIMBAD for this star--> * [[HD 94683|4266]] * [[HD 95208|4279]] * [[HD 95324|4290]] * [[HD 96544|4323]] * [[HD 96566|4325 (z<sup>1</sup>)]] * [[HD 96568|4326]] * [[HD 96706|4329]] * [[HD 97472|4349]] * [[HD 97583|4355]] * [[HD 97670|4361]] * [[HD 98560|4384]] | group5 = [[Henry Draper Catalogue|HD]] | list5 = * [[HD 49219|49219]] * [[HD 51608|51608]] * [[HD 53143|53143]] * [[HD 54967|54967]] * [[HD 63765|63765]] * [[HD 65216|65216]] * [[HD 79699|79699]] * [[HD 81896|81896]] * [[HD 82458|82458]] * [[HD 84046|84046]] * [[HD 89805|89805]] * [[HD 90074|90074]] * [[HD 90657|90657]] * [[HD 91094|91094]] * [[HD 92399|92399]] * [[HD 92536|92536]] * [[HD 93129A|93129A]] * [[HD 93250|93250]] * [[HD 93403|93403]] * [[HD 93645|93645]] * [[HD 93695|93695]] * [[HD 93738|93738]] * [[HD 93739|93739]] * [[HD 93843|93843]] * [[HD 94275|94275]] * [[HD 94305|94305]] * [[HD 94491|94491]] * [[HD 95086|95086]] * [[HD 95122|95122]] * [[HD 96088|96088]] * [[HD 97950|97950]] * [[HD 98025|98025]] | group6 = [[Gliese catalogue|Gliese]] | list6 = | group7 = Other | list7 = * [[BPM 6502]] * [[CPD−57° 2874]] * [[CPD−59° 2628]] * [[CPD−59° 2635]] * [[DENIS J081730.0−615520|DEN 0817−6155]] * [[AXP 1E 1048-59|1E 1048-59]] * [[FO 15]] * [[He 2-38]] * [[Innes' star]] * [[LHS 288]] * [[NGC 3603-A1]] * [[NGC 3603-B]] * [[NGC 3603-C]] * [[OGLE-TR-111]] * [[OGLE-TR-113]] * [[OGLE-TR-122]] * [[OGLE-TR-123]] * [[OGLE-TR-132]] * [[OGLE-TR-182]] * [[OGLE-TR-211]] * [[OGLE2-TR-L9]] * [[PSR J1048-5832]] * [[PSR J1119-6127]] * [[2S 0921-630]] * [[Sher 25]] * [[SS73 17]] * [[Tr 16-104]] * [[WR 16]] * [[WR 18]] * [[WR 20a]] * [[WR 21a]] * [[WR 22]] * [[WR 23]] * [[WR 24]] * [[WR 25]] * [[WR 30]] * [[WR 30a]] * [[WR 31a]] * [[WR 40]] * [[WR 42e]] * [[AWI0005x3s]] * [[WRA 751]] <!--Simbad ID is V432 Car--> }} |group2 = [[Star cluster|Star<br/>clusters]] |list2 = {{Navbox|subgroup |group1=[[Stellar association|Association]] |list1= * [[Carina OB1]] * [[Carina OB2]] |group2=[[Open cluster|Open]] |list2= * [[Collinder 228]] * [[IC 2602]] * [[IC 2714]] * [[NGC 2516]] * [[NGC 2609]] * [[NGC 3036]] * [[NGC 3114]] * [[NGC 3247]] * [[NGC 3255]] * [[NGC 3293]] * [[NGC 3324]] * [[NGC 3496]] * [[NGC 3519]] * [[NGC 3532]] * [[NGC 3572]] * [[NGC 3590]] * [[NGC 3603]] * [[Trumpler 14]] * [[Trumpler 15]] * [[Trumpler 16]] * [[Westerlund 2]] |group3=[[Globular cluster|Globular]] |list3= * [[NGC 2808]] }} |group3 = [[Nebula]]e |list3= {{Navbox|subgroup |group1=[[H II region|H II]] |list1= * [[Carina Nebula]] * [[NGC 3199]] * [[NGC 3576]] * [[NGC 3579]] * [[NGC 3581]] * [[NGC 3582]] * [[NGC 3584]] * [[NGC 3586]] * [[RCW 49]] |group2=[[Reflection nebula|Reflection]] |list2= * [[Homunculus Nebula]] * [[IC 2220]] * [[NGC 3503]] |group3=[[Planetary nebula|Planetary]] |list3= * [[He 2-36]] * [[Hen 2-47]] * [[IC 2448]] * [[IC 2501]] * [[IC 2553]] * [[NGC 2867]] * [[NGC 3211]] |group4=[[Supernova remnant|SNR]] |list4= * [[G290.1-0.8]] |group5=[[Pulsar wind nebula|Pulsar wind]] |list5= * [[IGR J11014−6103]] }} |group4 = [[Galaxy|Galaxies]] |list4= {{Navbox|subgroup |group1=[[Messier object|Messier]] |list1= |group2=[[New General Catalogue|NGC]] |list2= * [[NGC 2191|2191]] * [[NGC 2369|2369]] * [[NGC 2369A|2369A]] * [[NGC 2369B|2369B]] * [[NGC 2381|2381]] * [[NGC 2417|2417]] * [[NGC 2502|2502]] * [[NGC 2640|2640]] * [[NGC 2714|2714]] * [[NGC 2788|2788]] * [[NGC 2822|2822]] * [[NGC 2836|2836]] * [[NGC 2842|2842]] * [[NGC 2887|2887]] * [[NGC 3059|3059]] * [[NGC 3136|3136]] * [[NGC 3136A|3136A]] * [[NGC 3136B|3136B]] |group3=Other |list3= * [[Carina Dwarf Spheroidal Galaxy]] }} |group5=[[Galaxy cluster|Galaxy<br/>clusters]] |list5= * [[Abell 3391]] * [[Abell 3395]] * [[Bullet Cluster]] |group6=Other |list6= * [[GRB 000131]] * [[GRB 080916C]] }}<noinclude> == Documentation == {{Universe navboxes}} [[Category:Stars of constellation templates|Carina]] </noinclude> b3e9a604f6e67f2ecee2dbda375f4d9ba3b2bc17 Template:Starbox image 10 158 331 2022-06-16T17:59:55Z Canopus >MusikBot II 0 Changed protection settings for "[[Template:Starbox image]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 2501 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require extended confirmed access] (indefinite) [Move=Require administrator access] (indefinite)) wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><td colspan="2" style="text-align:center;"><div style="text-align: center; margin-left:auto; margin-right:auto">{{{image}}}{{#ifeq:{{#invoke:String|sub|{{{image}}}|1|4}}|<div||<br/>}}{{{caption}}}{{#if:{{{credit|}}}|<br>'''Credit''': ''{{{credit}}}''}}</div></tr></td><noinclude> |} {{Documentation}} </noinclude> 791822619c27809b308010e9b9fb71720d2f98f0 Module:Portal bar/styles.css 828 119 253 2022-06-17T04:36:59Z Canopus >Hike395 0 update styles to implement related portals text text/plain /* {{pp|small=y}} */ .portal-bar { font-size: 88%; font-weight: bold; display:flex; justify-content: center; align-items: baseline; } .portal-bar-bordered { padding: 0 2em; background-color: #fdfdfd; border: 1px solid #a2a9b1; clear: both; margin: 1em auto 0; } .portal-bar-related { font-size: 100%; justify-content: flex-start; } .portal-bar-unbordered { padding: 0 1.7em; margin-left: 0; } .portal-bar-header { margin: 0 1em 0 0.5em; flex: 0 0 auto; min-height: 24px; } .portal-bar-content { display:flex; flex-flow: row wrap; flex:0 1 auto; padding: 0.15em 0; column-gap: 1em; align-items: baseline; } .portal-bar-content-related { } .portal-bar-item { display:inline-block; margin:0.15em 0.2em; min-height:24px; line-height:24px; } @media screen and (max-width:768px) { .portal-bar { font-size: 88%; font-weight: bold; display:flex; flex-flow: column wrap; align-items: baseline; } .portal-bar-header { text-align: center; flex:0; padding-left: 0.5em; margin: 0 auto; } .portal-bar-related { font-size: 100%; align-items: flex-start; } .portal-bar-content { display:flex; flex-flow: row wrap; align-items: center; flex:0; column-gap: 1em; border-top: 1px solid #a2a9b1; margin: 0 auto; } .portal-bar-content-related { border-top: none; margin: 0; } } /* .navbox + .portal-bar-bordered */ .navbox + link + .portal-bar-bordered { margin-top: -1px; } .navbox + style + .portal-bar-bordered { margin-top: -1px; } .portal-bar + .navbox-styles + .navbox{ margin-top: -1px; } ec6e77726e7d76d00d66cefce85c3e7d2006d3c5 Module:Portal bar 828 118 251 2022-06-17T04:37:48Z Canopus >Hike395 0 implement related portals with larger icons Scribunto text/plain -- This module implements {{portal bar}}. require('Module:No globals') -- determine whether we're being called from a sandbox local isSandbox = mw.getCurrentFrame():getTitle():find('sandbox', 1, true) local sandbox = isSandbox and '/sandbox' or '' local portalModule = require('Module:Portal'..sandbox) local getImageName = portalModule._image local checkPortals = portalModule._checkPortals local processPortalArgs = portalModule._processPortalArgs local yesno = require( 'Module:Yesno' ) local getArgs = require('Module:Arguments').getArgs local p = {} local function sandboxVersion(s) return isSandbox and s.."-sand" or s end -- Builds the portal bar used by {{portal bar}}. function p._main( portals, args ) -- check for sensible args args = type(args) == "table" and args or {} -- Normalize arguments for key, default in pairs({border=true,redlinks=false,tracking=true}) do if args[key] == nil then args[key] = default end args[key] = yesno(args[key], default) end local nav = mw.html.create( 'div' ) :addClass(sandboxVersion('portal-bar')) :addClass( 'noprint metadata noviewer' ) :attr( 'role', 'navigation' ) :attr( 'aria-label' , 'Portals' ) :addClass(sandboxVersion(args.border and 'portal-bar-bordered' or 'portal-bar-unbordered')) local trackingCat = '' -- Allow any number of portals args.minPortals = 0 args.maxPortals = -1 -- Check to see whether there are redlinks, filter out unless args.redlink is true portals, trackingCat = checkPortals(portals, args) nav:wikitext(trackingCat) if #portals == 0 then return trackingCat end local related = yesno(args.related) if related then nav:addClass(sandboxVersion('portal-bar-related')) else local header = nav:tag('span') header:addClass(sandboxVersion('portal-bar-header')) header:wikitext('[[Wikipedia:Contents/Portals|Portal]]') if #portals > 1 then header:wikitext('s') end header:wikitext(':') end local container = nav:tag('div') container:addClass(sandboxVersion('portal-bar-content')) if related then container:addClass(sandboxVersion('portal-bar-content-related')) end local size = related and '27x25px' or '21x19px' for _, portal in ipairs( portals ) do container :tag( 'span' ) :addClass(sandboxVersion('portal-bar-item')) :wikitext( string.format('[[File:%s|%s]]&nbsp;[[Portal:%s|%s]]', getImageName(portal,true), size, portal, portal)) end local styleFile = 'Module:Portal bar'..sandbox..'/styles.css' return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = styleFile } } .. tostring( nav ) end -- Processes external arguments and sends them to the other functions. function p.main( frame ) local origArgs = getArgs(frame) local portals, args = processPortalArgs(origArgs) return p._main( portals, args ) end return p bb586a960cb56daaef2c7b7c994afbbd94772bbd Module:IPAc-en 828 81 177 2022-06-17T13:57:25Z Canopus >Nardog 0 lang Scribunto text/plain -- This module implements [[Template:IPAc-en]]. local data = mw.loadData('Module:IPAc-en/data') local p = {} -- Global container for tracking categories local categoryHandler = require('Module:Category handler').main local categories = {} -- Trims whitespace from a string local function trim(s) return s:match('^%s*(.-)%s*$') end -- This implements [[Template:Nowrap]]. local function makeNowrapSpan(s) local span = mw.html.create('span') :addClass('rt-commentedText') -- Works with [[MediaWiki:Gadget-ReferenceTooltips.js]] :addClass('nowrap') :wikitext(s) return tostring(span) end local function makePronunciationText(id) id = id and string.lower(trim(id)) if id and id ~= '' and data.pronunciation[id] then return data.pronunciation[id].text end end -- This adds a tooltip icon to a label. It implements [[Template:H:title]]. local function makeTooltip(label, tooltip) local span = mw.html.create('span') :attr('title', tooltip) :wikitext(label) return tostring(span) end local function formatPhonemeGroup(phonemes) if #phonemes > 0 then local span = mw.html.create('span') :css('border-bottom', '1px dotted') :wikitext(table.concat(phonemes)) return tostring(span) else return '' end end local function renderCategories() local ret = '' if categoryHandler{ true } then ret = {} for cat in pairs(categories) do table.insert(ret, string.format('[[Category:%s]]', cat)) end table.sort(ret) ret = table.concat(ret) else ret = '' end return ret end function p._main(args) local ret = {} local i = 0 -- Keeps track of numbered args -- Pronunciation do local pron = {} while true do i = i + 1 local pronItem = makePronunciationText(args[i]) if pronItem then pron[#pron + 1] = pronItem pron[#pron + 1] = ' ' else break end end if #pron > 0 then ret[#ret + 1] = string.format( '<small>%s</small>', table.concat(pron) ) end end -- Phonemes do -- Loop through the numbered args, separating them into phoneme groups -- and separator strings (both called "words" for convenience). We only -- underline the phoneme groups, not the separators. local words = {} words[#words + 1] = '/' -- Opening slash i = i - 1 -- Set up i again as it was changed in the pronunciation loop local id repeat local phonemes = {} local isWordEnd = false while not isWordEnd do i = i + 1 id = args[i] id = id and trim(id) if not id then isWordEnd = true words[#words + 1] = formatPhonemeGroup(phonemes) elseif id ~= '' then local t = data.phonemes[id] if not t then -- We were passed an invalid id. isWordEnd = true categories["Ill-formatted IPAc-en transclusions"] = true words[#words + 1] = formatPhonemeGroup(phonemes) words[#words + 1] = makeTooltip( string.format( "<strong class=\"error\">[invalid input: '%s']</strong>", id ), 'Unrecognized symbol' ) elseif not t.label then -- The data module contains bad data, so throw an error. error(string.format( "no label was found for id '%s'", tostring(id) )) elseif t.tooltip then -- We are dealing with a regular phoneme. phonemes[#phonemes + 1] = makeTooltip( t.label, t.tooltip ) else -- We are dealing with a separator. isWordEnd = true words[#words + 1] = formatPhonemeGroup(phonemes) words[#words + 1] = t.label end end end until not id words[#words + 1] = '/' -- Closing slash -- Wrap the words in a link to IPA help. local span = mw.html.create('span') -- Suppress Navigation popups and Page Previews (aka Hovercards) :addClass('IPA nopopups noexcerpt') :attr('lang', 'en-fonipa') :wikitext(string.format( '[[Help:IPA/English|%s]]', table.concat(words) )) ret[#ret + 1] = tostring(span) end -- Audio link do local file = args.audio and trim(args.audio) if file and file ~= '' then categories["Pages including recorded pronunciations"] = true ret[#ret + 1] = mw.getCurrentFrame():expandTemplate{ title = 'Template:IPA audio link', args = { file, attribution = args.attribution } } end end -- Nowrap and categories ret = makeNowrapSpan(table.concat(ret)) .. renderCategories() -- Reset the categories table in case we are run again. categories = {} return ret end function p.main(frame) return p._main(frame:getParent().args) end return p 62c540dcdc647c5bc63614ba04eabf7f645dd284 Main Page 0 1 1 2022-06-21T21:45:07Z MediaWiki default 1 Create main page wikitext text/x-wiki __NOTOC__ == Welcome to {{SITENAME}}! == This Main Page was created automatically and it seems it hasn't been replaced yet. === For the bureaucrat(s) of this wiki === Hello, and welcome to your new wiki! Thank you for choosing Miraheze for the hosting of your wiki, we hope you will enjoy our hosting. You can immediately start working on your wiki or whenever you want. Need help? No problem! We will help you with your wiki as needed. To start, try checking out these helpful links: * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) ==== I still don't understand X! ==== Well, that's no problem. Even if something isn't explained in the documentation/FAQ, we are still happy to help you. You can find us here: * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) === For visitors of this wiki === Hello, the default Main Page of this wiki (this page) has not yet been replaced by the bureaucrat(s) of this wiki. The bureaucrat(s) might still be working on a Main Page, so please check again later! 21236ac3f8d65e5563b6da6b70815ca6bf1e6616 10 1 2022-06-23T13:02:34Z SpaceMan 2 /* Welcome to AstroBase! */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. === Miraheze === Hello, and welcome to your new wiki! Thank you for choosing Miraheze for the hosting of your wiki, we hope you will enjoy our hosting. You can immediately start working on your wiki or whenever yo Need help? No problem! We will help you with your wiki as needed. To start, try checking out these helpful links: * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) === For visitors of this wiki === Hello, the default Main Page of this wiki (this page) has not yet been replaced by the bureaucrat(s) of this wiki. The bureaucrat(s) might still be working on a Main Page, so please check again later! __INDEX__ __NEWSECTIONLINK__ 30660bc82996a1236210ecb7a2998844cabc7032 11 10 2022-06-25T07:16:49Z SpaceMan 2 /* Miraheze */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. === Miraheze === your wiki as needed. To start, try checking out these helpful links: * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) === For visitors of this wiki === Hello, the default Main Page of this wiki (this page) has not yet been replaced by the bureaucrat(s) of this wiki. The bureaucrat(s) might still be working on a Main Page, so please check again later! __INDEX__ __NEWSECTIONLINK__ 8dd8420a12b1aeb4e52c821af048315d0d558c0c 12 11 2022-06-25T07:17:35Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. === Miraheze === * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) __INDEX__ __NEWSECTIONLINK__ 781d5b730c902622fbe7aef268cc6e2528e4f032 13 12 2022-06-25T07:20:59Z SpaceMan 2 Protected "[[Main Page]]" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. === Miraheze === * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) __INDEX__ __NEWSECTIONLINK__ 781d5b730c902622fbe7aef268cc6e2528e4f032 30 13 2022-07-02T03:39:22Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. ===Quick List=== [[Special:ListUsers]] === Miraheze === * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) __INDEX__ __NEWSECTIONLINK__ bfca6b7c52b7e5922c1fa9ce6b3b8c4781465b1e Template:FlowMention 10 2 2 2022-06-23T12:50:41Z Flow talk page manager 3 /* Automatically created by Flow */ wikitext text/x-wiki @[[User:{{{1|Example}}}|{{{2|{{{1|Example}}}}}}]] 98786e33cb63444ac23e3cf2bdbcab2d9501a6e7 Template:LQT Moved thread stub converted to Flow 10 3 3 2022-06-23T12:50:43Z Flow talk page manager 3 /* Automatically created by Flow */ wikitext text/x-wiki This post by {{{author}}} was moved on {{{date}}}. You can find it at [[{{{title}}}]]. 792a92295d0603dc3cb5c46e15d4e42af9659414 Template:LQT page converted to Flow 10 4 4 2022-06-23T12:50:43Z Flow talk page manager 3 /* Automatically created by Flow */ wikitext text/x-wiki Previous page history was archived for backup purposes at <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> on {{#time: Y-m-d|{{{date}}}}}. c988d60d1df8c49bcce1f4f94a9c2a5318faf0d3 Template:Archive for converted LQT page 10 5 5 2022-06-23T12:50:44Z Flow talk page manager 3 /* Automatically created by Flow */ wikitext text/x-wiki This page is an archived LiquidThreads page. <strong>Do not edit the contents of this page</strong>. Please direct any additional comments to the [[{{{from}}}|current talk page]]. 6f2232948be664f5eec18e4b7a6219814d38a478 Template:LQT post imported with suppressed user 10 6 6 2022-06-23T12:50:45Z Flow talk page manager 3 /* Automatically created by Flow */ wikitext text/x-wiki This revision was imported from LiquidThreads with a suppressed user. It has been reassigned to the current user. 0eb25fe53f4e146ddc0b16b14bd40d6069e56c06 Template:LQT post imported with different signature user 10 7 7 2022-06-23T12:50:46Z Flow talk page manager 3 /* Automatically created by Flow */ wikitext text/x-wiki <em>This post was posted by [[User:{{{authorUser}}}|{{{authorUser}}}]], but signed as [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em> 047294b02240e1b8526ad076eb47a07e98747bac Template:Wikitext talk page converted to Flow 10 8 8 2022-06-23T12:50:47Z Flow talk page manager 3 /* Automatically created by Flow */ wikitext text/x-wiki Previous discussion was archived at <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> on {{#time: Y-m-d|{{{date}}}}}. 69c9712008fdef423f0f0332a7d4ffcfe65e6e76 Template:Archive for converted wikitext talk page 10 9 9 2022-06-23T12:50:48Z Flow talk page manager 3 /* Automatically created by Flow */ wikitext text/x-wiki This page is an archive. <strong>Do not edit the contents of this page</strong>. Please direct any additional comments to the [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|current talk page]]. de059e2d945be0557b47d689299d8bd96e9699ed Astronomy 0 10 14 2022-06-25T07:37:25Z SpaceMan 2 Astronomy wikitext text/x-wiki *Definition* Astronomy (from Ancient Greek ἀστρονομία (astronomía) 'science that studies the laws of the stars') is a natural science that studies celestial objects and phenomena. It uses [[mathematics]], [[physics]], and [[chemistry][ in order to explain their origin and evolution. Objects of interest include [[planets]], [[moons]], [[stars]], [[nebulae]], [[galaxies]], and [[comets]]. Relevant phenomena include [[supernova explosions]], [[gamma ray bursts]], [[quasars]], [[blazars]], [[pulsars]], and [[cosmic microwave background radiation]]. More generally, astronomy studies everything that originates beyond Earth's atmosphere. Cosmology is a branch of astronomy that studies the universe as a whole. Astronomy is one of the oldest natural sciences. The early civilizations in recorded history made methodical observations of the night sky. These include the Babylonians, Greeks, Indians, Egyptians, Chinese, Maya, and many ancient indigenous peoples of the Americas. In the past, astronomy included disciplines as diverse as astrometry, celestial navigation, observational astronomy, and the making of calendars. Nowadays, professional astronomy is often said to be the same as astrophysics. Professional astronomy is split into observational and theoretical branches. Observational astronomy is focused on acquiring data from observations of astronomical objects. This data is then analyzed using basic principles of physics. Theoretical astronomy is oriented toward the development of computer or analytical models to describe astronomical objects and phenomena. These two fields complement each other. Theoretical astronomy seeks to explain observational results and observations are used to confirm theoretical results. Astronomy is one of the few sciences in which amateurs play an active role. This is especially true for the discovery and observation of transient events. Amateur astronomers have helped with many important discoveries, such as finding new comets. [[File:Https://wallpapercave.com/wp/to2ELne.jpg|thumb|alt=Astronomy |Astronomy ]] f0036893c0468ca7a25211fc6c19136284a7cc34 15 14 2022-06-25T07:38:17Z SpaceMan 2 wikitext text/x-wiki **Definition** Astronomy (from Ancient Greek ἀστρονομία (astronomía) 'science that studies the laws of the stars') is a natural science that studies celestial objects and phenomena. It uses [[mathematics]], [[physics]], and [[chemistry][ in order to explain their origin and evolution. Objects of interest include [[planets]], [[moons]], [[stars]], [[nebulae]], [[galaxies]], and [[comets]]. Relevant phenomena include [[supernova explosions]], [[gamma ray bursts]], [[quasars]], [[blazars]], [[pulsars]], and [[cosmic microwave background radiation]]. More generally, astronomy studies everything that originates beyond Earth's atmosphere. Cosmology is a branch of astronomy that studies the universe as a whole. Astronomy is one of the oldest natural sciences. The early civilizations in recorded history made methodical observations of the night sky. These include the Babylonians, Greeks, Indians, Egyptians, Chinese, Maya, and many ancient indigenous peoples of the Americas. In the past, astronomy included disciplines as diverse as astrometry, celestial navigation, observational astronomy, and the making of calendars. Nowadays, professional astronomy is often said to be the same as astrophysics. Professional astronomy is split into observational and theoretical branches. Observational astronomy is focused on acquiring data from observations of astronomical objects. This data is then analyzed using basic principles of physics. Theoretical astronomy is oriented toward the development of computer or analytical models to describe astronomical objects and phenomena. These two fields complement each other. Theoretical astronomy seeks to explain observational results and observations are used to confirm theoretical results. Astronomy is one of the few sciences in which amateurs play an active role. This is especially true for the discovery and observation of transient events. Amateur astronomers have helped with many important discoveries, such as finding new comets. 58c0adbf5c037ef5dd5859caf51f995e820b352a 16 15 2022-06-25T07:39:09Z SpaceMan 2 wikitext text/x-wiki == Definition == * Astronomy (from Ancient Greek ἀστρονομία (astronomía) 'science that studies the laws of the stars') is a natural science that studies celestial objects and phenomena. It uses [[mathematics]], [[physics]], and [[chemistry][ in order to explain their origin and evolution. Objects of interest include [[planets]], [[moons]], [[stars]], [[nebulae]], [[galaxies]], and [[comets]]. Relevant phenomena include [[supernova explosions]], [[gamma ray bursts]], [[quasars]], [[blazars]], [[pulsars]], and [[cosmic microwave background radiation]]. More generally, astronomy studies everything that originates beyond Earth's atmosphere. Cosmology is a branch of astronomy that studies the universe as a whole. Astronomy is one of the oldest natural sciences. The early civilizations in recorded history made methodical observations of the night sky. These include the Babylonians, Greeks, Indians, Egyptians, Chinese, Maya, and many ancient indigenous peoples of the Americas. In the past, astronomy included disciplines as diverse as astrometry, celestial navigation, observational astronomy, and the making of calendars. Nowadays, professional astronomy is often said to be the same as astrophysics. Professional astronomy is split into observational and theoretical branches. Observational astronomy is focused on acquiring data from observations of astronomical objects. This data is then analyzed using basic principles of physics. Theoretical astronomy is oriented toward the development of computer or analytical models to describe astronomical objects and phenomena. These two fields complement each other. Theoretical astronomy seeks to explain observational results and observations are used to confirm theoretical results. Astronomy is one of the few sciences in which amateurs play an active role. This is especially true for the discovery and observation of transient events. Amateur astronomers have helped with many important discoveries, such as finding new comets. 36bb58025d70aeb143f78d09b9173144d022677e 17 16 2022-06-25T07:39:32Z SpaceMan 2 wikitext text/x-wiki == Definition == * Astronomy (from Ancient Greek ἀστρονομία (astronomía) 'science that studies the laws of the stars') is a natural science that studies celestial objects and phenomena. It uses [[mathematics]], [[physics]], and <nowiki>[[chemistry]]</nowiki>in order to explain their origin and evolution. Objects of interest include [[planets]], [[moons]], [[stars]], [[nebulae]], [[galaxies]], and [[comets]]. Relevant phenomena include [[supernova explosions]], [[gamma ray bursts]], [[quasars]], [[blazars]], [[pulsars]], and [[cosmic microwave background radiation]]. More generally, astronomy studies everything that originates beyond Earth's atmosphere. Cosmology is a branch of astronomy that studies the universe as a whole. Astronomy is one of the oldest natural sciences. The early civilizations in recorded history made methodical observations of the night sky. These include the Babylonians, Greeks, Indians, Egyptians, Chinese, Maya, and many ancient indigenous peoples of the Americas. In the past, astronomy included disciplines as diverse as astrometry, celestial navigation, observational astronomy, and the making of calendars. Nowadays, professional astronomy is often said to be the same as astrophysics. Professional astronomy is split into observational and theoretical branches. Observational astronomy is focused on acquiring data from observations of astronomical objects. This data is then analyzed using basic principles of physics. Theoretical astronomy is oriented toward the development of computer or analytical models to describe astronomical objects and phenomena. These two fields complement each other. Theoretical astronomy seeks to explain observational results and observations are used to confirm theoretical results. Astronomy is one of the few sciences in which amateurs play an active role. This is especially true for the discovery and observation of transient events. Amateur astronomers have helped with many important discoveries, such as finding new comets. 41251f1d20d2d46adef9e54cc69fb38cc9a25906 19 17 2022-06-25T07:45:49Z SpaceMan 2 /* Definition */ wikitext text/x-wiki == Definition == * Astronomy (from Ancient Greek ἀστρονομία (astronomía) 'science that studies the laws of the stars') is a natural science that studies celestial objects and phenomena. It uses [[mathematics]], [[physics]], and <nowiki>[[chemistry]]</nowiki>in order to explain their origin and evolution. Objects of interest include [[planets]], [[moons]], [[stars]], [[nebulae]], [[galaxies]], and [[comets]]. Relevant phenomena include [[supernova explosions]], [[gamma ray bursts]], [[quasars]], [[blazars]], [[pulsars]], and [[cosmic microwave background radiation]]. More generally, astronomy studies everything that originates beyond Earth's atmosphere. Cosmology is a branch of astronomy that studies the universe as a whole. Astronomy is one of the oldest natural sciences. The early civilizations in recorded history made methodical observations of the night sky. These include the Babylonians, Greeks, Indians, Egyptians, Chinese, Maya, and many ancient indigenous peoples of the Americas. In the past, astronomy included disciplines as diverse as astrometry, celestial navigation, observational astronomy, and the making of calendars. Nowadays, professional astronomy is often said to be the same as astrophysics. Professional astronomy is split into observational and theoretical branches. Observational astronomy is focused on acquiring data from observations of astronomical objects. This data is then analyzed using basic principles of physics. Theoretical astronomy is oriented toward the development of computer or analytical models to describe astronomical objects and phenomena. These two fields complement each other. Theoretical astronomy seeks to explain observational results and observations are used to confirm theoretical results. Astronomy is one of the few sciences in which amateurs play an active role. This is especially true for the discovery and observation of transient events. Amateur astronomers have helped with many important discoveries, such as finding new comets. [[File:Astronomy.jpg|thumb|Astronomy picture]] e89c3607361d4dcbc60666b4c807d95a0f4b0abe File:Astronomy.jpg 6 11 18 2022-06-25T07:44:35Z SpaceMan 2 Uploaded own work with UploadWizard wikitext text/x-wiki =={{int:filedesc}}== {{Information |description={{en|1=Astronomy picture}} |date=2022-06-25 |source={{own}} |author=[[User:SpaceMan|SpaceMan]] |permission= |other versions= }} =={{int:license-header}}== {{self|cc-by-sa-4.0}} [[Category:Astronomy pics]] f2bd0fb0e8a5433da50d52f3832df75f9e600725 Acceleration 0 12 20 2022-06-25T15:21:03Z SpaceMan 2 Acceleration wikitext text/x-wiki ==Definition== It is defined as the change in the velocity of an object per unit time. If the velocity of an object changes frIt is defined as the change in the om an initial value u to final value v in time t, then acceleration a is given by Acceleration = (final velocity - initial velocity )/ Time ==Properties== SI unit of acceleration is m/s² It is a [https://wikiofspaceman.miraheze.org/wiki/Vector_quantity vector quantity], its direction is in the direction of change in velocity. It may be positive, negative or zero. If an object is moving with constant or uniform [[velocity]], then its acceleration is zero. ==Uniform acceleration== A body is said to have uniform acceleration, if it travels in a straight line and its velocity increases or decreases by equal [[magnitude]] in equal intervals of time. For example : (ii) The [[motion]] of a bicycle going down the slope of a road (when the rider is not pedaling and [[air resistance]] is negligible). ==Non-Uniform acceleration== A body is said to have non-uniform acceleration, if its velocity changes by unequal magnitude in equal intervals of time. For example - The motion of a car on a crowded road. ==Retardation or deceleration== A body is said to be retarded if the magnitude of its velocity decreases with time. In this case, the final velocity of the moving body is less than the initial velocity i.e., v<u. For example - When a person applies brake on a moving car, its velocity decreases with time. For example, if acceleration is a = - 5 m/s ^ 2 we can write this as the deceleration or retardation is taking place at 5 m/s² or you can also put it as acceleration in the opposite direction at the rate of 5 m/s². 7b0eebda6dbc4a0e447a95553cbe2dd800038524 21 20 2022-06-25T15:22:01Z SpaceMan 2 /* Properties */ wikitext text/x-wiki ==Definition== It is defined as the change in the velocity of an object per unit time. If the velocity of an object changes frIt is defined as the change in the om an initial value u to final value v in time t, then acceleration a is given by Acceleration = (final velocity - initial velocity )/ Time ==Properties== SI unit of acceleration is m/s² It is a Vector quantity], its direction is in the direction of change in velocity. It may be positive, negative or zero. If an object is moving with constant or uniform [[velocity]], then its acceleration is zero. ==Uniform acceleration== A body is said to have uniform acceleration, if it travels in a straight line and its velocity increases or decreases by equal [[magnitude]] in equal intervals of time. For example : (ii) The [[motion]] of a bicycle going down the slope of a road (when the rider is not pedaling and [[air resistance]] is negligible). ==Non-Uniform acceleration== A body is said to have non-uniform acceleration, if its velocity changes by unequal magnitude in equal intervals of time. For example - The motion of a car on a crowded road. ==Retardation or deceleration== A body is said to be retarded if the magnitude of its velocity decreases with time. In this case, the final velocity of the moving body is less than the initial velocity i.e., v<u. For example - When a person applies brake on a moving car, its velocity decreases with time. For example, if acceleration is a = - 5 m/s ^ 2 we can write this as the deceleration or retardation is taking place at 5 m/s² or you can also put it as acceleration in the opposite direction at the rate of 5 m/s². c4f0b1c84cd426997808a81b9f8e5eb76d02ea72 22 21 2022-06-25T15:22:21Z SpaceMan 2 /* Properties */ wikitext text/x-wiki ==Definition== It is defined as the change in the velocity of an object per unit time. If the velocity of an object changes frIt is defined as the change in the om an initial value u to final value v in time t, then acceleration a is given by Acceleration = (final velocity - initial velocity )/ Time ==Properties== SI unit of acceleration is m/s² It is a [[Vector quantity]], its direction is in the direction of change in velocity. It may be positive, negative or zero. If an object is moving with constant or uniform [[velocity]], then its acceleration is zero. ==Uniform acceleration== A body is said to have uniform acceleration, if it travels in a straight line and its velocity increases or decreases by equal [[magnitude]] in equal intervals of time. For example : (ii) The [[motion]] of a bicycle going down the slope of a road (when the rider is not pedaling and [[air resistance]] is negligible). ==Non-Uniform acceleration== A body is said to have non-uniform acceleration, if its velocity changes by unequal magnitude in equal intervals of time. For example - The motion of a car on a crowded road. ==Retardation or deceleration== A body is said to be retarded if the magnitude of its velocity decreases with time. In this case, the final velocity of the moving body is less than the initial velocity i.e., v<u. For example - When a person applies brake on a moving car, its velocity decreases with time. For example, if acceleration is a = - 5 m/s ^ 2 we can write this as the deceleration or retardation is taking place at 5 m/s² or you can also put it as acceleration in the opposite direction at the rate of 5 m/s². 24354aacf7c5ca60b90e1d20bd9319a4b1ea48ea Astrophysics 0 24 48 2022-06-26T08:22:32Z Astrophysics >Citation bot 0 Add: bibcode. | [[WP:UCB|Use this bot]]. [[WP:DBUG|Report bugs]]. | Suggested by Abductive | #UCB_toolbar wikitext text/x-wiki {{short description|Branch of astronomy}} {{About|the use of physics to determine the nature of astronomical objects|the use of physics to determine their positions and motions|Celestial mechanics|the physical study of the largest-scale structures of the universe|Physical cosmology|the journal|Astrophysics (journal)}} {{TopicTOC-Physics}} '''Astrophysics''' is a science that employs the methods and principles of [[physics]] and [[chemistry]] in the study of [[astronomical object]]s and phenomena.<ref>{{cite book |title=Astrophysics in a Nutshell |first=Dan |last=Maoz |date=23 February 2016 |publisher=Princeton University Press |pages=272 |isbn=9781400881178 |url=https://www.google.com/books/edition/Astrophysics_in_a_Nutshell/bmBeCwAAQBAJ?hl=en&gbpv=1&dq=%22astrophysics+is%22&pg=PA1&printsec=frontcover}}</ref><ref>{{cite web | title=astrophysics | publisher=Merriam-Webster, Incorporated | url=http://www.merriam-webster.com/dictionary/astrophysics | access-date=2011-05-22 | archive-url= https://web.archive.org/web/20110610085146/http://www.merriam-webster.com/dictionary/astrophysics| archive-date= 10 June 2011 | url-status= live}}</ref> As one of the founders of the discipline said, Astrophysics "seeks to ascertain the nature of the heavenly bodies, rather than their positions or motions in space–''what'' they are, rather than ''where'' they are."<ref>{{Citation | last = Keeler | first = James E. | author-link = James E. Keeler | title = The Importance of Astrophysical Research and the Relation of Astrophysics to the Other Physical Sciences | journal = The Astrophysical Journal | volume = 6 | issue = 4 | pages = 271–288 | date = November 1897 | bibcode = 1897ApJ.....6..271K |doi = 10.1086/140401 | pmid = 17796068 }}</ref> Among the subjects studied are the [[Sun]], other [[star]]s, [[galaxy|galaxies]], [[extrasolar planet]]s, the [[interstellar medium]] and the [[cosmic microwave background]].<ref name="nasa.gov">{{cite web|url=https://science.nasa.gov/astrophysics/focus-areas/|title=Focus Areas – NASA Science|work=nasa.gov}}</ref><ref>{{cite encyclopedia|url=https://www.britannica.com/EBchecked/topic/40047/astronomy|title=astronomy|encyclopedia=Encyclopædia Britannica}}</ref> Emissions from these objects are examined across all parts of the [[electromagnetic spectrum]], and the properties examined include [[luminosity]], [[density]], [[temperature]], and [[chemistry|chemical]] composition. Because astrophysics is a very broad subject, ''astrophysicists'' apply concepts and methods from many disciplines of physics and chemistry, including [[classical mechanics]], [[electromagnetism]], [[statistical mechanics]], [[thermodynamics]], [[quantum mechanics]], [[theory of relativity|relativity]], [[nuclear physics|nuclear]] and [[particle physics]], and [[atomic, molecular, and optical physics|atomic and molecular physics]]. In practice, modern astronomical research often involves a substantial amount of work in the realms of [[Theoretical physics|theoretical]] and observational physics. Some areas of study for astrophysicists include their attempts to determine the properties of [[dark matter]], [[dark energy]], [[black holes]], and other [[celestial bodies]]; and the [[Cosmogony|origin]] and [[ultimate fate of the universe]].<ref name="nasa.gov"/> Topics also studied by theoretical astrophysicists include [[Formation and evolution of the Solar System|Solar System formation and evolution]]; [[stellar dynamics]] and [[Stellar evolution|evolution]]; [[galaxy formation and evolution]]; [[magnetohydrodynamics]]; [[large-scale structure of the universe|large-scale structure]] of [[matter]] in the universe; origin of [[cosmic ray]]s; [[general relativity]], [[special relativity]], [[quantum cosmology|quantum]] and [[physical cosmology]], including [[string theory|string]] cosmology and [[astroparticle physics]]. ==History== [[Image:NIEdot362.jpg|thumb|left|200px|Early 1900s comparison of elemental, solar, and stellar spectra]] Astronomy is an ancient science, long separated from the study of terrestrial physics. In the [[Aristotle|Aristotelian]] worldview, bodies in the sky appeared to be unchanging [[Celestial spheres|spheres]] whose only motion was uniform motion in a circle, while the earthly world was the realm which underwent [[On Generation and Corruption|growth and decay]] and in which natural motion was in a straight line and ended when the moving object reached its [[Telos|goal]]. Consequently, it was held that the celestial region was made of a fundamentally different kind of matter from that found in the terrestrial sphere; either [[Fire (classical element)|Fire]] as maintained by [[Plato]], or [[Aether (classical element)|Aether]] as maintained by [[Aristotle#Physics|Aristotle]].<ref>{{cite book | last = Lloyd | first = G. E. R. | author-link = G. E. R. Lloyd | title = Aristotle: The Growth and Structure of His Thought | publisher = Cambridge University Press | year = 1968 | location = Cambridge | pages = [https://archive.org/details/aristotlegrowths0000lloy/page/134 134–135] | url =https://archive.org/details/aristotlegrowths0000lloy| url-access = registration | isbn = 978-0-521-09456-6}}</ref><ref>{{cite book | last = Cornford | first = Francis MacDonald | author-link = F. M. Cornford | title = Plato's Cosmology: The ''Timaeus'' of Plato translated, with a running commentary | publisher = Bobbs Merrill Co | date = c. 1957 | orig-year = 1937 | location = Indianapolis | page = 118}}</ref> During the 17th century, natural philosophers such as [[Galileo]],<ref>{{Citation | last = Galilei | first = Galileo | author-link = Galileo Galilei | editor-last = Van Helden | editor-first = Albert | publication-date = 1989 | title = Sidereus Nuncius or The Sidereal Messenger | publisher = University of Chicago Press | location = Chicago | pages = 21, 47 | isbn = 978-0-226-27903-9 | date = 1989-04-15 }}</ref> [[Descartes]],<ref>{{Cite encyclopedia |author=Edward Slowik |title=Descartes' Physics |url=http://plato.stanford.edu/entries/descartes-physics/ |encyclopedia=[[Stanford Encyclopedia of Philosophy]] |date=2013 |orig-year=2005 |access-date=2015-07-18}}</ref> and [[Isaac Newton|Newton]]<ref>{{Citation | last = Westfall | first = Richard S. | author-link = Richard S. Westfall | publication-date = 1980 | title = Never at Rest: A Biography of Isaac Newton | publisher = Cambridge University Press | location = Cambridge | pages = [https://archive.org/details/neveratrestbiogr00west/page/731 731–732] | isbn = 978-0-521-27435-7 | date = 1983-04-29 | url-access = registration | url = https://archive.org/details/neveratrestbiogr00west/page/731 }}</ref> began to maintain that the celestial and terrestrial regions were made of similar kinds of material and were subject to the same [[Physical law|natural laws]].<ref name = Burtt/> Their challenge was that the tools had not yet been invented with which to prove these assertions.<ref>{{Cite journal |author=Ladislav Kvasz |title=Galileo, Descartes, and Newton – Founders of the Language of Physics |url=http://www.physics.sk/aps/pubs/2012/aps-12-06/aps-12-06.pdf |publisher=Institute of Philosophy, [[Academy of Sciences of the Czech Republic]] |date=2013 |access-date=2015-07-18}}</ref> For much of the nineteenth century, astronomical research was focused on the routine work of measuring the positions and computing the motions of astronomical objects.<ref>{{Citation | last = Case | first = Stephen | date = 2015 | title = 'Land-marks of the universe': John Herschel against the background of positional astronomy | journal = Annals of Science | volume = 72 | issue = 4 | pages = 417–434 | doi = 10.1080/00033790.2015.1034588 | pmid = 26221834 | quote = The great majority of astronomers working in the early nineteenth century were not interested in stars as physical objects. Far from being bodies with physical properties to be investigated, the stars were seen as markers measured in order to construct an accurate, detailed and precise background against which solar, lunar and planetary motions could be charted, primarily for terrestrial applications.|bibcode = 2015AnSci..72..417C | doi-access = free }}</ref><ref>{{Citation | last = Donnelly | first = Kevin | date = September 2014 | title = On the boredom of science: positional astronomy in the nineteenth century | journal = The British Journal for the History of Science | volume = 47 | issue = 3 | pages = 479–503 | doi = 10.1017/S0007087413000915 | s2cid = 146382057 | url = https://zenodo.org/record/999531 }}</ref> A new astronomy, soon to be called astrophysics, began to emerge when [[William Hyde Wollaston]] and [[Joseph von Fraunhofer]] independently discovered that, when decomposing the light from the Sun, a multitude of [[Fraunhofer lines|dark lines]] (regions where there was less or no light) were observed in the [[Visible spectrum|spectrum]].<ref>{{cite book | last=Hearnshaw|first=J.B. | title=The analysis of starlight | date=1986 | publisher=Cambridge University Press | location=Cambridge | isbn=978-0-521-39916-6 | pages=23–29}}</ref> By 1860 the physicist, [[Gustav Kirchhoff]], and the chemist, [[Robert Bunsen]], had demonstrated that the [[Absorption spectroscopy#Absorption spectrum|dark lines]] in the solar spectrum corresponded to [[Emission spectrum|bright lines]] in the spectra of known gases, specific lines corresponding to unique [[chemical element]]s.<ref>{{citation | last = Kirchhoff | first = Gustav | author-link = Gustav Kirchhoff |title=Ueber die Fraunhofer'schen Linien | journal=Annalen der Physik | volume=185 |issue=1 | pages=148–150 | date=1860 | bibcode = 1860AnP...185..148K | doi=10.1002/andp.18601850115| url = https://zenodo.org/record/1423666 }}</ref> Kirchhoff deduced that the dark lines in the solar spectrum are caused by [[absorption (optics)|absorption]] by [[chemical elements]] in the Solar atmosphere.<ref>{{citation | last = Kirchhoff | first = Gustav | author-link = Gustav Kirchhoff | title=Ueber das Verhältniss zwischen dem Emissionsvermögen und dem Absorptionsvermögen der Körper für Wärme und Licht |journal=Annalen der Physik |volume=185 | issue=2 | pages=275–301 | date=1860 | bibcode = 1860AnP...185..275K | doi=10.1002/andp.18601850205| url=https://zenodo.org/record/1423668 | doi-access=free }}</ref> In this way it was proved that the chemical elements found in the Sun and stars were also found on Earth. Among those who extended the study of solar and stellar spectra was [[Norman Lockyer]], who in 1868 detected radiant, as well as dark lines in solar spectra. Working with chemist [[Edward Frankland]] to investigate the spectra of elements at various temperatures and pressures, he could not associate a yellow line in the solar spectrum with any known elements. He thus claimed the line represented a new element, which was called [[helium]], after the Greek [[Helios]], the Sun personified.<ref>{{citation | last = Cortie | first = A. L. | title = Sir Norman Lockyer, 1836 – 1920 | journal = The Astrophysical Journal | year = 1921 | volume = 53 | pages = 233–248 | bibcode = 1921ApJ....53..233C | doi=10.1086/142602}}</ref><ref>{{Citation | last = Jensen | first = William B.|author1-link=William B. Jensen | title = Why Helium Ends in "-ium" | journal = Journal of Chemical Education | volume = 81 | issue = 7 | pages = 944–945 | year = 2004 | url = http://www.che.uc.edu/jensen/W.%20B.%20Jensen/Reprints/115.%20Helium.pdf | doi=10.1021/ed081p944 | bibcode = 2004JChEd..81..944J }}</ref> In 1885, [[Edward C. Pickering]] undertook an ambitious program of stellar spectral classification at [[Harvard College Observatory]], in which a team of [[Harvard Computers|woman computers]], notably [[Williamina Fleming]], [[Antonia Maury]], and [[Annie Jump Cannon]], classified the spectra recorded on photographic plates. By 1890, a catalog of over 10,000 stars had been prepared that grouped them into thirteen spectral types. Following Pickering's vision, by 1924 Cannon expanded the [[Henry Draper Catalogue|catalog]] to nine volumes and over a quarter of a million stars, developing the [[Stellar classification#Harvard spectral classification|Harvard Classification Scheme]] which was accepted for worldwide use in 1922.<ref>{{Citation|last1=Hetherington |first1=Norriss S. |last2=McCray |first2=W. Patrick |author2-link=W. Patrick McCray |editor-last=Weart |editor-first=Spencer R. |editor-link=Spencer R. Weart |title=Spectroscopy and the Birth of Astrophysics |publisher=American Institute of Physics, Center for the History of Physics |url=https://www.aip.org/history/cosmology/tools/tools-spectroscopy.htm |access-date=July 19, 2015 |url-status=dead |archive-url=https://web.archive.org/web/20150907133751/https://www.aip.org/history/cosmology/tools/tools-spectroscopy.htm |archive-date=September 7, 2015 }}</ref> In 1895, [[George Ellery Hale]] and [[James E. Keeler]], along with a group of ten associate editors from Europe and the United States,<ref name = Hale1895>{{Citation | last = Hale | first = George Ellery | title = The Astrophysical Journal | author-link = George Ellery Hale | journal = The Astrophysical Journal | volume = 1 | issue = 1 | pages = 80–84 | bibcode = 1895ApJ.....1...80H | doi = 10.1086/140011| year = 1895 }}</ref> established [[The Astrophysical Journal|''The Astrophysical Journal: An International Review of Spectroscopy and Astronomical Physics'']].<ref>{{List journal | journal = The Astrophysical Journal | volume = 1 | issue = 1 }}</ref> It was intended that the journal would fill the gap between journals in astronomy and physics, providing a venue for publication of articles on astronomical applications of the spectroscope; on laboratory research closely allied to astronomical physics, including wavelength determinations of metallic and gaseous spectra and experiments on radiation and absorption; on theories of the Sun, Moon, planets, comets, meteors, and nebulae; and on instrumentation for telescopes and laboratories.<ref name = Hale1895/> Around 1920, following the discovery of the [[Hertzsprung–Russell diagram]] still used as the basis for classifying stars and their evolution, [[Arthur Eddington]] anticipated the discovery and mechanism of [[nuclear fusion]] processes in [[star]]s, in his paper ''The Internal Constitution of the Stars''.<ref name=eddington> {{ Citation | last = Eddington | first = A. S. | author-link = Arthur Eddington | date = October 1920 | title = The Internal Constitution of the Stars | journal = The Scientific Monthly | volume = 11 | issue = 4 | pages = 297–303 | doi = 10.1126/science.52.1341.233 | jstor = 6491 | pmid = 17747682 | bibcode = 1920Sci....52..233E | url = https://zenodo.org/record/1429642 }}</ref><ref name=eddington2>{{cite journal | bibcode = 1916MNRAS..77...16E | title = On the radiative equilibrium of the stars | journal=Monthly Notices of the Royal Astronomical Society | volume=77 | pages=16–35 | last1=Eddington|first1=A. S. | author-link = Arthur Eddington | year=1916 | doi=10.1093/mnras/77.1.16| doi-access=free }}</ref> At that time, the source of stellar energy was a complete mystery; Eddington correctly speculated that the source was [[nuclear fusion|fusion]] of hydrogen into helium, liberating enormous energy according to Einstein's equation ''E = mc<sup>2</sup>''. This was a particularly remarkable development since at that time fusion and thermonuclear energy, and even that stars are largely composed of [[hydrogen]] (see [[metallicity]]), had not yet been discovered.<ref>{{Cite book|title=Fusion|last1=McCracken|editor-last2=Stott|editor-first2=Peter|editor-last=McCracken|editor-first=Garry|last2=Stott|first2=Peter|first1=Garry|url=http://www.sciencedirect.com/science/article/pii/B9780123846563000027|language=en|doi=10.1016/b978-0-12-384656-3.00002-7|pages=13|isbn=978-0-12-384656-3|location=Boston|date=2013-01-01|publisher=Academic Press|quote=Eddington had realized that there would be a mass loss if four hydrogen atoms combined to form a single helium atom. Einstein’s equivalence of mass and energy led directly to the suggestion that this could be the long-sought process that produces the energy in the stars! It was an inspired guess, all the more remarkable because the structure of the nucleus and the mechanisms of these reactions were not fully understood.|edition=Second}}</ref> In 1925 Cecilia Helena Payne (later [[Cecilia Payne-Gaposchkin]]) wrote an influential doctoral dissertation at [[Radcliffe College]], in which she applied ionization theory to stellar atmospheres to relate the spectral classes to the temperature of stars.<ref>{{citation |last=Payne |first=C. H. |year=1925 |title=Stellar Atmospheres; A Contribution to the Observational Study of High Temperature in the Reversing Layers of Stars |type=PhD Thesis |publisher=[[Radcliffe College]] | location = Cambridge, Massachusetts | publication-date = 1925 |bibcode=1925PhDT.........1P }}</ref> Most significantly, she discovered that hydrogen and helium were the principal components of stars. Despite Eddington's suggestion, this discovery was so unexpected that her dissertation readers convinced her to modify the conclusion before publication. However, later research confirmed her discovery.<ref>{{citation | last = Haramundanis | first = Katherine | editor-last = Hockey | editor-first = Thomas | editor2-last = Trimble | editor2-first = Virginia | editor2-link = Virginia Louise Trimble | editor3-last = Williams | editor3-first = Thomas R. | title = Biographical Encyclopedia of Astronomers | chapter = Payne-Gaposchkin [Payne], Cecilia Helena | access-date = July 19, 2015 |year=2007 | chapter-url=https://books.google.com/books?id=t-BF1CHkc50C | pages=876–878 | publisher = Springer | location = New York | isbn = 978-0-387-30400-7 }}</ref> By the end of the 20th century, studies of astronomical spectra had expanded to cover wavelengths extending from radio waves through optical, x-ray, and gamma wavelengths.<ref>{{cite conference |mode=cs2 |last1=Biermann |first1=Peter L. |last2=Falcke |first2=Heino |author2-link=Heino Falcke |editor-last=Panvini |editor-first=Robert S. |editor2-last=Weiler |editor2-first=Thomas J. |date=1998 |book-title=Fundamental particles and interactions: Frontiers in contemporary physics an international lecture and workshop series. AIP Conference Proceedings |title=Frontiers of Astrophysics: Workshop Summary |volume=423 |publisher=American Institute of Physics |pages=236–248 |isbn=1-56396-725-1 |bibcode=1998AIPC..423..236B |doi=10.1063/1.55085|arxiv=astro-ph/9711066 }}</ref> In the 21st century, it further expanded to include observations based on [[gravitational waves]]. ==Observational astrophysics== [[Image:N 63A- Chandra and Hubble - Heic0507f.tif|thumb|right|200px|Supernova remnant LMC N 63A imaged in x-ray (blue), optical (green) and radio (red) wavelengths. The X-ray glow is from material heated to about ten million degrees Celsius by a shock wave generated by the supernova explosion.]] [[Observational astronomy]] is a division of the astronomical science that is concerned with recording and interpreting data, in contrast with [[theoretical astrophysics]], which is mainly concerned with finding out the measurable implications of physical [[model (abstract)|models]]. It is the practice of observing [[celestial object]]s by using [[telescope]]s and other astronomical apparatus. The majority of astrophysical observations are made using the [[electromagnetic spectrum]]. * [[Radio astronomy]] studies radiation with a [[wavelength]] greater than a few millimeters. Example areas of study are [[radio waves]], usually emitted by cold objects such as [[interstellar gas]] and dust clouds; the cosmic microwave background radiation which is the [[redshift]]ed light from the [[Big Bang]]; [[pulsar]]s, which were first detected at [[microwave]] frequencies. The study of these waves requires very large [[radio telescope]]s. * [[Infrared astronomy]] studies radiation with a wavelength that is too long to be visible to the naked eye but is shorter than radio waves. Infrared observations are usually made with telescopes similar to the familiar [[optical]] telescopes. Objects colder than stars (such as planets) are normally studied at infrared frequencies. * [[Optical astronomy]] was the earliest kind of astronomy. Telescopes paired with a [[charge-coupled device]] or [[spectroscope]]s are the most common instruments used. The Earth's [[atmosphere]] interferes somewhat with optical observations, so [[adaptive optics]] and [[space telescope]]s are used to obtain the highest possible image quality. In this wavelength range, stars are highly visible, and many chemical spectra can be observed to study the chemical composition of stars, galaxies, and [[nebula]]e. * [[Ultraviolet]], [[X-ray astronomy|X-ray]] and [[gamma ray astronomy]] study very energetic processes such as [[binary pulsar]]s, [[black hole]]s, [[magnetar]]s, and many others. These kinds of radiation do not penetrate the Earth's atmosphere well. There are two methods in use to observe this part of the electromagnetic spectrum—[[space-based telescope]]s and ground-based [[imaging air Cherenkov telescope]]s (IACT). Examples of [[Observatory|Observatories]] of the first type are [[RXTE]], the [[Chandra X-ray Observatory]] and the [[Compton Gamma Ray Observatory]]. Examples of IACTs are the [[High Energy Stereoscopic System]] (H.E.S.S.) and the [[MAGIC (telescope)|MAGIC]] telescope. Other than electromagnetic radiation, few things may be observed from the Earth that originate from great distances. A few [[gravitational wave]] observatories have been constructed, but gravitational waves are extremely difficult to detect. [[Neutrino]] observatories have also been built, primarily to study our Sun. Cosmic rays consisting of very high-energy particles can be observed hitting the Earth's atmosphere. Observations can also vary in their time scale. Most optical observations take minutes to hours, so phenomena that change faster than this cannot readily be observed. However, historical data on some objects is available, spanning [[century|centuries]] or [[millennia]]. On the other hand, radio observations may look at events on a millisecond timescale ([[millisecond pulsar]]s) or combine years of data ([[Rotation-powered pulsar|pulsar deceleration]] studies). The information obtained from these different timescales is very different. The study of our very own Sun has a special place in observational astrophysics. Due to the tremendous distance of all other stars, the Sun can be observed in a kind of detail unparalleled by any other star. Our understanding of our own Sun serves as a guide to our understanding of other stars. The topic of how stars change, or stellar evolution, is often modeled by placing the varieties of star types in their respective positions on the [[Hertzsprung–Russell diagram]], which can be viewed as representing the state of a stellar object, from birth to destruction. ==Theoretical astrophysics== {{see also|Theoretical astronomy}} Theoretical astrophysicists use a wide variety of tools which include [[mathematical model|analytical models]] (for example, [[polytrope]]s to approximate the behaviors of a star) and [[computation]]al [[Numerical analysis|numerical simulations]]. Each has some advantages. Analytical models of a process are generally better for giving insight into the heart of what is going on. Numerical models can reveal the existence of phenomena and effects that would otherwise not be seen.<ref>{{Citation |first=H. |last=Roth |title=A Slowly Contracting or Expanding Fluid Sphere and its Stability |journal=[[Physical Review]] |volume=39 |issue=3 |pages=525–529 |year=1932 |doi=10.1103/PhysRev.39.525 |bibcode = 1932PhRv...39..525R }}</ref><ref>{{Citation |first=A.S. |last=Eddington |title=Internal Constitution of the Stars |journal=Science |location=New York |publisher=Cambridge University Press |orig-year=1926 |year=1988 |volume=52 |issue=1341 |pages=233–240 |doi=10.1126/science.52.1341.233 |isbn=978-0-521-33708-3 |pmid=17747682 |bibcode=1920Sci....52..233E |url=https://zenodo.org/record/1429642 }}</ref> Theorists in astrophysics endeavor to create theoretical models and figure out the observational consequences of those models. This helps allow observers to look for data that can refute a model or help in choosing between several alternate or conflicting models. Theorists also try to generate or modify models to take into account new data. In the case of an inconsistency, the general tendency is to try to make minimal modifications to the model to fit the data. In some cases, a large amount of inconsistent data over time may lead to total abandonment of a model. Topics studied by theoretical astrophysicists include stellar dynamics and evolution; galaxy formation and evolution; magnetohydrodynamics; large-scale structure of matter in the universe; origin of cosmic rays; general relativity and physical cosmology, including [[string theory|string]] cosmology and astroparticle physics. Astrophysical relativity serves as a tool to gauge the properties of large-scale structures for which gravitation plays a significant role in physical phenomena investigated and as the basis for [[black hole]] (''astro'')physics and the study of [[gravitational waves]]. Some widely accepted and studied theories and models in astrophysics, now included in the [[Lambda-CDM model]], are the [[Big Bang]], [[cosmic inflation]], dark matter, dark energy and fundamental theories of physics. == Popularization == The roots of astrophysics can be found in the seventeenth century emergence of a unified physics, in which the same laws applied to the celestial and terrestrial realms.<ref name = Burtt>{{Citation | last = Burtt | first = Edwin Arthur | author-link = Edwin Arthur Burtt | publication-date = 2003 | orig-year = First published 1924 | title = The Metaphysical Foundations of Modern Science | edition = second revised | publisher = Dover Publications | location = Mineola, NY | pages = 30, 41, 241–2 | isbn = 978-0-486-42551-1 | url = https://books.google.com/books?id=G9WBMa1Rz_kC | year = 2003 }}</ref> There were scientists who were qualified in both physics and astronomy who laid the firm foundation for the current science of astrophysics. In modern times, students continue to be drawn to astrophysics due to its popularization by the [[Royal Astronomical Society]] and notable [[Science education|educators]] such as prominent professors [[Lawrence Krauss]], [[Subrahmanyan Chandrasekhar]], [[Stephen Hawking]], [[Hubert Reeves]], [[Carl Sagan]], [[Neil deGrasse Tyson]] and [[Patrick Moore]]. The efforts of the early, late, and present scientists continue to attract young people to study the history and science of astrophysics.<ref>{{Cite web |author=D. Mark Manley |title=Famous Astronomers and Astrophysicists |url=http://cnr2.kent.edu/~manley/astronomers.html |publisher=[[Kent State University]] |date=2012 |access-date=2015-07-17}}</ref><ref>{{Cite web |author=The science.ca team |title=Hubert Reeves – Astronomy, Astrophysics and Space Science |url=http://www.science.ca/scientists/scientistprofile.php?pID=213 |publisher=GCS Research Society |date=2015 |access-date=2015-07-17}}</ref><ref>{{Cite web |title=Neil deGrasse Tyson |url=http://www.haydenplanetarium.org/tyson/ |publisher=[[Hayden Planetarium]] |date=2015 |access-date=2015-07-17}}</ref> ==See also== {{cols|colwidth=21em}} * [[Astrochemistry]] * [[List of astronomical observatories|Astronomical observatories]] * [[Astronomical spectroscopy]] * [[Astroparticle physics]] * [[Gravitational-wave astronomy]] * [[Hertzsprung–Russell diagram]] * [[High-energy astronomy]] * [[List of important publications in physics#Astrophysics|Important publications in astrophysics]] * [[List of astronomers]] (includes astrophysicists) * [[Neutrino astronomy]] (future prospects) * [[Timeline of gravitational physics and relativity]] * [[Timeline of knowledge about galaxies, clusters of galaxies, and large-scale structure]] * [[Timeline of white dwarfs, neutron stars, and supernovae]] {{colend}} ==References== {{Reflist}} ==Further reading== * {{Citation | last = Longair | first = Malcolm S. | author-link = Malcolm S. Longair | title = The Cosmic Century: A History of Astrophysics and Cosmology | place = Cambridge | publisher = Cambridge University Press | year = 2006 | isbn = 978-0-521-47436-8 | url-access = registration | url = https://archive.org/details/cosmiccenturyhis0000long }} * [http://www.scholarpedia.org/article/Encyclopedia:Astrophysics Astrophysics] [[Scholarpedia]] Expert articles ==External links== {{Wikibooks|Astrophysics}} {{Library resources box|onlinebooks=yes}} * [http://www.aanda.org/ ''Astronomy and Astrophysics'', a European Journal] * [http://iopscience.iop.org/0004-637X/ ''Astrophysical Journal''] * [http://www.aip.org/history/cosmology/index.htm Cosmic Journey: A History of Scientific Cosmology] from the American Institute of Physics * [http://www.worldscinet.com/ijmpd/ijmpd.shtml ''International Journal of Modern Physics D''] from [[World Scientific]] * [http://www.scienceresourceworld.com/publications/journals/astronomy_journals.html List and directory of peer-reviewed Astronomy / Astrophysics Journals] * [http://www.astro.ucla.edu/~wright/cosmolog.htm Ned Wright's Cosmology Tutorial, UCLA] {{Physics-footer}} {{Astronomy subfields}} {{Astronomy navbox}} {{Portal bar|Physics|Astronomy|Stars|Spaceflight|Outer space|Solar System}} {{Authority control}} [[Category:Astrophysics| ]] [[Category:Astronomical sub-disciplines]] bd2c54352b5f33382b25fe37da4e112ea4e9afdc Module:Val 828 43 101 2022-06-30T03:19:56Z Canopus >Johnuniq 0 use i18n from [[Module:Val/sandbox]] added by [[User:Moroboshi]] Scribunto text/plain -- For Template:Val, output a number and optional unit. -- Format options include scientific and uncertainty notations. local numdot = '.' -- decimal mark (use ',' for Italian) local numsep = ',' -- group separator (use ' ' for Italian) local mtext = { -- Message and other text that should be localized. ['mt-bad-exponent'] = 'exponent parameter (<b>e</b>)', ['mt-parameter'] = 'parameter ', ['mt-not-number'] = 'is not a valid number', ['mt-cannot-range'] = 'cannot use a range if the first parameter includes "e"', ['mt-need-range'] = 'needs a range in parameter 2', ['mt-should-range'] = 'should be a range', ['mt-cannot-with-e'] = 'cannot be used if the first parameter includes "e"', ['mt-not-range'] = 'does not accept a range', ['mt-cannot-e'] = 'cannot use e notation', ['mt-too-many-parameter'] = 'too many parameters', ['mt-need-number'] = 'need a number after the last parameter because it is a range.', ['mt-ignore-parameter4'] = 'Val parameter 4 ignored', ['mt-val-not-supported'] = 'Val parameter "%s=%s" is not supported', ['mt-invalid-scale'] = 'Unit "%s" has invalid scale "%s"', ['mt-both-u-ul'] = 'unit (<b>u</b>) and unit with link (<b>ul</b>) are both specified, only one is allowed.', ['mt-both-up-upl'] = 'unit per (<b>up</b>) and unit per with link (<b>upl</b>) are both specified, only one is allowed.', } local data_module = 'Module:Val/units' local convert_module = 'Module:Convert' local function valerror(msg, nocat, iswarning) -- Return formatted message text for an error or warning. -- Can append "#FormattingError" to URL of a page with a problem to find it. local anchor = '<span id="FormattingError"></span>' local body, category if nocat or mw.title.getCurrentTitle():inNamespaces(1, 2, 3, 5) then -- No category in Talk, User, User_talk, or Wikipedia_talk. category = '' else category = '[[Category:Pages with incorrect formatting templates use]]' end iswarning = false -- problems are infrequent so try showing large error so editor will notice if iswarning then body = '<sup class="noprint Inline-Template" style="white-space:nowrap;">' .. '[[Template:Val|<span title="' .. msg:gsub('"', '&quot;') .. '">warning</span>]]</sup>' else body = '<strong class="error">' .. 'Error in &#123;&#123;[[Template:val|val]]&#125;&#125;: ' .. msg .. '</strong>' end return anchor .. body .. category end local range_types = { -- No need for '&nbsp;' because nowrap applies to all output. [","] = ", ", ["by"] = " by ", ["-"] = "–", ["–"] = "–", ["and"] = " and ", ["or"] = " or " , ["to"] = " to " , ["x"] = " × ", ["×"] = " × ", ["/"] = "/", } local range_repeat_unit = { -- WP:UNIT wants unit repeated when a "multiply" range is used. ["x"] = true, ["×"] = true, } local function extract_item(index, numbers, arg) -- Extract an item from arg and store the result in numbers[index]. -- If no argument or if argument is valid, return nil (no error); -- otherwise, return an error message. -- The stored result is: -- * a table for a number (empty if there was no specified number); or -- * a string for range text -- Input like 1e3 is regarded as invalid for all except argument 1 -- which accepts e notation as an alternative to the 'e' argument. -- Input group separators are removed. local which = index local function fail(msg) local description if which == 'e' then description = mtext['mt-bad-exponent'] else description = mtext['mt-parameter'] .. which end return description .. ' ' .. (msg or mtext['mt-not-number']) .. '.' end local result = {} local range = range_types[arg] if range then if type(index) == 'number' and (index % 2 == 0) then if index == 2 then if numbers[1] and numbers[1].exp then return fail(mtext['mt-cannot-range']) end numbers.has_ranges = true else if not numbers.has_ranges then return fail(mtext['mt-need-range']) end end numbers[index] = range if range_repeat_unit[arg] then -- Any "repeat" range forces unit (if any) to be repeated for all items. numbers.isrepeat = true end return nil end return fail(mtext['mt-not-range']) end if numbers.has_ranges and type(index) == 'number' and (index % 2 == 0) then return fail(mtext['mt-should-range']) end if index == 'e' then local e = numbers[1] and numbers[1].exp if e then if arg then return fail(mtext['mt-cannot-with-e']) end arg = e which = 1 end end if arg and arg ~= '' then arg = arg:gsub(numsep, '') if numdot ~= '.' then arg = arg:gsub(numdot, '.') end if arg:sub(1, 1) == '(' and arg:sub(-1) == ')' then result.parens = true arg = arg:sub(2, -2) end local a, b = arg:match('^(.+)[Ee](.+)$') if a then if index == 1 then arg = a result.exp = b else return fail(mtext['mt-cannot-e']) end end local isnegative, propersign, prefix local minus = '−' prefix, arg = arg:match('^(.-)([%d.]+)$') local value = tonumber(arg) if not value then return fail() end if arg:sub(1, 1) == '.' then arg = '0' .. arg end if prefix == '' then -- Ignore. elseif prefix == '±' then -- Display for first number, ignore for others. if index == 1 then propersign = '±' end elseif prefix == '+' then propersign = '+' elseif prefix == '-' or prefix == minus then propersign = minus isnegative = true else return fail() end result.clean = arg result.sign = propersign or '' result.value = isnegative and -value or value end numbers[index] = result return nil -- no error end local function get_args(numbers, args) -- Extract arguments and store the results in numbers. -- Return nothing (no error) if ok; otherwise, return an error message. for index = 1, 99 do local which = index local arg = args[which] -- has been trimmed if not arg then which = 'e' arg = args[which] end local msg = extract_item(which, numbers, arg) if msg then return msg end if which == 'e' then break end if index > 19 then return mtext['mt-too-many-parameter'] end end if numbers.has_ranges and (#numbers % 2 == 0) then return mtext['mt-need-number'] end end local function get_scale(text, ucode) -- Return the value of text as a number, or throw an error. -- This supports extremely basic expressions of the form: -- a / b -- a ^ b -- where a and b are numbers or 'pi'. local n = tonumber(text) if n then return n end n = text:gsub('pi', math.pi) for _, op in ipairs({ '/', '^' }) do local a, b = n:match('^(.-)' .. op .. '(.*)$') if a then a = tonumber(a) b = tonumber(b) if a and b then if op == '/' then return a / b elseif op == '^' then return a ^ b end end break end end error(string.format(mtext['mt-invalid-scale'], ucode, text)) end local function get_builtin_unit(ucode, definitions) -- Return table of information for the specified built-in unit, or nil if not known. -- Each defined unit code must be followed by two spaces (not tab characters). local _, pos = definitions:find('\n' .. ucode .. ' ', 1, true) if pos then local endline = definitions:find('%s*\n', pos) if endline then local result = {} local n = 0 local text = definitions:sub(pos + 1, endline - 1):gsub('%s%s+', '\t') for item in (text .. '\t'):gmatch('(%S.-)\t') do if item == 'ALIAS' then result.alias = true elseif item == 'ANGLE' then result.isangle = true result.nospace = true elseif item == 'NOSPACE' then result.nospace = true elseif item == 'SI' then result.si = true else n = n + 1 if n == 1 then local link, symbol = item:match('^%[%[([^|]+)|(.+)%]%]$') if link then result.symbol = symbol result.link = link n = 2 else result.symbol = item end elseif n == 2 then result.link = item elseif n == 3 then result.scale_text = item result.scale = get_scale(item, ucode) else result.more_ignored = item break end end end if result.si then local s = result.symbol if ucode == 'mc' .. s or ucode == 'mu' .. s then result.ucode = 'µ' .. s -- unit code for convert should be this end end if n >= 2 or (n >= 1 and result.alias) then return result end -- Ignore invalid definition, treating it as a comment. end end end local function convert_lookup(ucode, value, scaled_top, want_link, si, options) local lookup = require(convert_module)._unit return lookup(ucode, { value = value, scaled_top = scaled_top, link = want_link, si = si, sort = options.sortable, }) end local function get_unit(ucode, value, scaled_top, options) local want_link = options.want_link if scaled_top then want_link = options.want_per_link end local data = mw.loadData(data_module) local result = options.want_longscale and get_builtin_unit(ucode, data.builtin_units_long_scale) or get_builtin_unit(ucode, data.builtin_units) local si, use_convert if result then if result.alias then ucode = result.symbol use_convert = true end if result.scale then -- Setting si means convert will use the unit as given, and the sort key -- will be calculated from the value without any extra scaling that may -- occur if convert found the unit code. For example, if val defines the -- unit 'year' with a scale and if si were not set, convert would also apply -- its own scale because convert knows that a year is 31,557,600 seconds. si = { result.symbol, result.link } value = value * result.scale end if result.si then ucode = result.ucode or ucode si = { result.symbol, result.link } use_convert = true end else result = {} use_convert = true end local convert_unit = convert_lookup(ucode, value, scaled_top, want_link, si, options) result.sortkey = convert_unit.sortspan if use_convert then result.text = convert_unit.text result.scaled_top = convert_unit.scaled_value else if want_link then result.text = '[[' .. result.link .. '|' .. result.symbol .. ']]' else result.text = result.symbol end result.scaled_top = value end return result end local function makeunit(value, options) -- Return table of information for the requested unit and options, or -- return nil if no unit. options = options or {} local unit local ucode = options.u local percode = options.per if ucode then unit = get_unit(ucode, value, nil, options) elseif percode then unit = { nospace = true, scaled_top = value } else return nil end local text = unit.text or '' local sortkey = unit.sortkey if percode then local function bracketed(code, text) return code:find('[*./]') and '(' .. text .. ')' or text end local perunit = get_unit(percode, 1, unit.scaled_top, options) text = (ucode and bracketed(ucode, text) or '') .. '/' .. bracketed(percode, perunit.text) sortkey = perunit.sortkey end if not (unit.nospace or options.nospace) then text = '&nbsp;' .. text end return { text = text, isangle = unit.isangle, sortkey = sortkey } end local function list_units(mode) -- Return wikitext to list the built-in units. -- A unit code should not contain wikimarkup so don't bother escaping. local data = mw.loadData(data_module) local definitions = data.builtin_units .. data.builtin_units_long_scale local last_was_blank = true local n = 0 local result = {} local function add(line) if line == '' then last_was_blank = true else if last_was_blank and n > 0 then n = n + 1 result[n] = '' end last_was_blank = false n = n + 1 result[n] = line end end local si_prefixes = { -- These are the prefixes recognized by convert; u is accepted for micro. y = 'y', z = 'z', a = 'a', f = 'f', p = 'p', n = 'n', u = 'µ', ['µ'] = 'µ', m = 'm', c = 'c', d = 'd', da = 'da', h = 'h', k = 'k', M = 'M', G = 'G', T = 'T', P = 'P', E = 'E', Z = 'Z', Y = 'Y', } local function is_valid(ucode, unit) if unit and not unit.more_ignored then assert(type(unit.symbol) == 'string' and unit.symbol ~= '') if unit.alias then if unit.link or unit.scale_text or unit.si then return false end end if unit.si then if unit.scale_text then return false end ucode = unit.ucode or ucode local base = unit.symbol if ucode == base then unit.display = base return true end local plen = #ucode - #base if plen > 0 then local prefix = si_prefixes[ucode:sub(1, plen)] if prefix and ucode:sub(plen + 1) == base then unit.display = prefix .. base return true end end else unit.display = unit.symbol return true end end return false end local lookup = require(convert_module)._unit local function show_convert(ucode, unit) -- If a built-in unit defines a scale or sets the SI flag, any unit defined in -- convert is not used (the scale or SI prefix's scale is used for a sort key). -- If there is no scale or SI flag, and the unit is not defined in convert, -- the sort key may not be correct; this allows such units to be identified. if not (unit.si or unit.scale_text) then if mode == 'convert' then unit.show = not lookup(unit.alias and unit.symbol or ucode).unknown unit.show_text = 'CONVERT' elseif mode == 'unknown' then unit.show = lookup(unit.alias and unit.symbol or ucode).unknown unit.show_text = 'UNKNOWN' elseif not unit.alias then -- Show convert's scale in square brackets ('[1]' for an unknown unit). -- Don't show scale for an alias because it's misleading for temperature -- and an alias is probably not useful for anything else. local scale = lookup(ucode, {value=1, sort='on'}).scaled_value if type(scale) == 'number' then scale = string.format('%.5g', scale):gsub('e%+?(%-?)0*(%d+)', 'e%1%2') else scale = '?' end unit.show = true unit.show_text = '[' .. scale .. ']' end end end for line in definitions:gmatch('([^\n]*)\n') do local pos, _ = line:find(' ', 1, true) if pos then local ucode = line:sub(1, pos - 1) local unit = get_builtin_unit(ucode, '\n' .. line .. '\n') if is_valid(ucode, unit) then show_convert(ucode, unit) local flags, text if unit.alias then text = unit.symbol else text = '[[' .. unit.link .. '|' .. unit.display .. ']]' end if unit.isangle then unit.nospace = nil -- don't show redundant flag end for _, f in ipairs({ { 'alias', 'ALIAS' }, { 'isangle', 'ANGLE' }, { 'nospace', 'NOSPACE' }, { 'si', 'SI' }, { 'scale_text', unit.scale_text }, { 'show', unit.show_text }, }) do if unit[f[1]] then local t = f[2] if t:match('^%u+$') then t = '<small>' .. t .. '</small>' end if flags then flags = flags .. ' ' .. t else flags = t end end end if flags then text = text .. ' • ' .. flags end add(ucode .. ' = ' .. text .. '<br />') else add(line .. ' ◆ <b>invalid definition</b><br />') end else add(line) end end return table.concat(result, '\n') end local delimit_groups = require('Module:Gapnum').groups local function delimit(sign, numstr, fmt) -- Return sign and numstr (unsigned digits or numdot only) after formatting. -- Four-digit integers are not formatted with gaps. fmt = (fmt or ''):lower() if fmt == 'none' or (fmt == '' and #numstr == 4 and numstr:match('^%d+$')) then return sign .. numstr end -- Group number by integer and decimal parts. -- If there is no decimal part, delimit_groups returns only one table. local ipart, dpart = delimit_groups(numstr) local result if fmt == 'commas' then result = sign .. table.concat(ipart, numsep) if dpart then result = result .. numdot .. table.concat(dpart) end else -- Delimit with a small gap by default. local groups = {} groups[1] = table.remove(ipart, 1) for _, v in ipairs(ipart) do table.insert(groups, '<span style="margin-left:.25em;">' .. v .. '</span>') end if dpart then table.insert(groups, numdot .. (table.remove(dpart, 1) or '')) for _, v in ipairs(dpart) do table.insert(groups, '<span style="margin-left:.25em;">' .. v .. '</span>') end end result = sign .. table.concat(groups) end return result end local function sup_sub(sup, sub, align) -- Return the same result as Module:Su except val defaults to align=right. if align == 'l' or align == 'left' then align = 'left' elseif align == 'c' or align == 'center' then align = 'center' else align = 'right' end return '<span style="display:inline-block;margin-bottom:-0.3em;vertical-align:-0.4em;line-height:1.2em;font-size:85%;text-align:' .. align .. ';">' .. sup .. '<br />' .. sub .. '</span>' end local function range_text(items, unit_table, options) local fmt = options.fmt local nend = items.nend or '' if items.isrepeat or unit_table.isangle then nend = nend .. unit_table.text end local text = '' for i = 1, #items do if i % 2 == 0 then text = text .. items[i] else text = text .. delimit(items[i].sign, items[i].clean, fmt) .. nend end end return text end local function uncertainty_text(uncertainty, unit_table, options) local angle, text, need_parens if unit_table.isangle then angle = unit_table.text end local upper = uncertainty.upper or {} local lower = uncertainty.lower or {} local uncU = upper.clean if uncU then local fmt = options.fmt local uncL = lower.clean if uncL then uncU = delimit('+', uncU, fmt) .. (upper.errend or '') uncL = delimit('−', uncL, fmt) .. (lower.errend or '') if angle then uncU = uncU .. angle uncL = uncL .. angle end text = (angle or '') .. '<span style="margin-left:0.3em;">' .. sup_sub(uncU, uncL, options.align) .. '</span>' else if upper.parens then text = '(' .. uncU .. ')' -- old template did not delimit else text = (angle or '') .. '<span style="margin-left:0.3em;margin-right:0.15em;">±</span>' .. delimit('', uncU, fmt) need_parens = true end if uncertainty.errend then text = text .. uncertainty.errend end if angle then text = text .. angle end end else if angle then text = angle end end return text, need_parens end local function _main(values, unit_spec, options) if options.sandbox then data_module = data_module .. '/sandbox' convert_module = convert_module .. '/sandbox' end local action = options.action if action then if action == 'list' then -- Kludge: am using the align parameter (a=xxx) for type of list. return list_units(options.align) end return valerror('invalid action "' .. action .. '".', options.nocat) end local number = values.number or (values.numbers and values.numbers[1]) or {} local e_10 = options.e or {} local novalue = (number.value == nil and e_10.clean == nil) local fmt = options.fmt local want_sort = true local sortable = options.sortable if sortable == 'off' or (sortable == nil and novalue) then want_sort = false elseif sortable == 'debug' then -- Same as sortable = 'on' but the sort key is displayed. else sortable = 'on' end local sort_value = 1 if want_sort then sort_value = number.value or 1 if e_10.value and sort_value ~= 0 then -- The 'if' avoids {{val|0|e=1234}} giving an invalid sort_value due to overflow. sort_value = sort_value * 10^e_10.value end end local unit_table = makeunit(sort_value, { u = unit_spec.u, want_link = unit_spec.want_link, per = unit_spec.per, want_per_link = unit_spec.want_per_link, nospace = novalue, want_longscale = unit_spec.want_longscale, sortable = sortable, }) local sortkey if unit_table then if want_sort then sortkey = unit_table.sortkey end else unit_table = { text = '' } if want_sort then sortkey = convert_lookup('dummy', sort_value, nil, nil, nil, { sortable = sortable }).sortspan end end local final_unit = unit_table.isangle and '' or unit_table.text local e_text, n_text, need_parens local uncertainty = values.uncertainty if uncertainty then if number.clean then n_text = delimit(number.sign, number.clean, fmt) .. (number.nend or '') local text text, need_parens = uncertainty_text(uncertainty, unit_table, options) if text then n_text = n_text .. text end else n_text = '' end else if values.numbers.isrepeat then final_unit = '' end n_text = range_text(values.numbers, unit_table, options) need_parens = true end if e_10.clean then if need_parens then n_text = '(' .. n_text .. ')' end e_text = '10<sup>' .. delimit(e_10.sign, e_10.clean, fmt) .. '</sup>' if number.clean then e_text = '<span style="margin-left:0.25em;margin-right:0.15em;">×</span>' .. e_text end else e_text = '' end local result = (sortkey or '') .. (options.prefix or '') .. n_text .. e_text .. final_unit .. (options.suffix or '') if result ~= '' then result = '<span class="nowrap">' .. result .. '</span>' end return result .. (options.warning or '') end local function check_parameters(args, has_ranges, nocat) -- Return warning text for the first problem parameter found, or nothing if ok. local whitelist = { a = true, action = true, debug = true, e = true, ['end'] = true, errend = true, ['+errend'] = true, ['-errend'] = true, fmt = true, ['long scale'] = true, long_scale = true, longscale = true, nocategory = true, p = true, s = true, sortable = true, u = true, ul = true, up = true, upl = true, } for k, v in pairs(args) do if type(k) == 'string' and not whitelist[k] then local warning = string.format(mtext['mt-val-not-supported'], k, v) return valerror(warning, nocat, true) end end if not has_ranges and args[4] then return valerror(mtext['mt-ignore-parameter4'], nocat, true) end end local function main(frame) local getArgs = require('Module:Arguments').getArgs local args = getArgs(frame, {wrappers = { 'Template:Val' }}) local nocat = args.nocategory local numbers = {} -- table of number tables, perhaps with range text local msg = get_args(numbers, args) if msg then return valerror(msg, nocat) end if args.u and args.ul then return valerror(mtext['mt-both-u-ul'], nocat) end if args.up and args.upl then return valerror(mtext['mt-both-up-upl'], nocat) end local values if numbers.has_ranges then -- Multiple values with range separators but no uncertainty. numbers.nend = args['end'] values = { numbers = numbers, } else -- A single value with optional uncertainty. local function setfield(i, dst, src) local v = args[src] if v then if numbers[i] then numbers[i][dst] = v else numbers[i] = { [dst] = v } end end end setfield(1, 'nend', 'end') setfield(2, 'errend', '+errend') setfield(3, 'errend', '-errend') values = { number = numbers[1], uncertainty = { upper = numbers[2], lower = numbers[3], errend = args.errend, } } end local unit_spec = { u = args.ul or args.u, want_link = args.ul ~= nil, per = args.upl or args.up, want_per_link = args.upl ~= nil, want_longscale = (args.longscale or args.long_scale or args['long scale']) == 'on', } local options = { action = args.action, align = args.a, e = numbers.e, fmt = args.fmt, nocat = nocat, prefix = args.p, sandbox = string.find(frame:getTitle(), 'sandbox', 1, true) ~= nil, sortable = args.sortable or (args.debug == 'yes' and 'debug' or nil), suffix = args.s, warning = check_parameters(args, numbers.has_ranges, nocat), } return _main(values, unit_spec, options) end return { main = main, _main = _main } 899cf01cf6a449e10309108c9de56689e4205d5c Module:Citation/CS1/Date validation 828 54 123 2022-07-01T17:45:21Z Canopus >Trappist the monk 0 sync from sandbox; Scribunto text/plain --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local add_prop_cat, is_set, in_array, set_message, substitute, wrap_style; -- imported functions from selected Module:Citation/CS1/Utilities local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration --[[--------------------------< F I L E - S C O P E D E C L A R A T I O N S >-------------------------------- File-scope variables are declared here ]] local lang_object = mw.getContentLanguage(); -- used by is_valid_accessdate(), is_valid_year(), date_name_xlate(); TODO: move to ~/Configuration? local year_limit; -- used by is_valid_year() --[=[-------------------------< I S _ V A L I D _ A C C E S S D A T E >---------------------------------------- returns true if: Wikipedia start date <= accessdate < today + 2 days Wikipedia start date is 2001-01-15T00:00:00 UTC which is 979516800 seconds after 1970-01-01T00:00:00 UTC (the start of Unix time) accessdate is the date provided in |access-date= at time 00:00:00 UTC today is the current date at time 00:00:00 UTC plus 48 hours if today is 2015-01-01T00:00:00 then adding 24 hours gives 2015-01-02T00:00:00 – one second more than today adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow This function does not work if it is fed month names for languages other than English. Wikimedia #time: parser apparently doesn't understand non-English date month names. This function will always return false when the date contains a non-English month name because good1 is false after the call to lang.formatDate(). To get around that call this function with YYYY-MM-DD format dates. ]=] local function is_valid_accessdate (accessdate) local good1, good2; local access_ts, tomorrow_ts; -- to hold Unix time stamps representing the dates good1, access_ts = pcall (lang_object.formatDate, lang_object, 'U', accessdate ); -- convert accessdate value to Unix timestamp good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow if good1 and good2 then -- lang.formatDate() returns a timestamp in the local script which which tonumber() may not understand access_ts = tonumber (access_ts) or lang_object:parseFormattedNumber (access_ts); -- convert to numbers for the comparison; tomorrow_ts = tonumber (tomorrow_ts) or lang_object:parseFormattedNumber (tomorrow_ts); else return false; -- one or both failed to convert to Unix time stamp end if 979516800 <= access_ts and access_ts < tomorrow_ts then -- Wikipedia start date <= accessdate < tomorrow's date return true; else return false; -- accessdate out of range end end --[[--------------------------< G E T _ M O N T H _ N U M B E R >---------------------------------------------- returns a number according to the month in a date: 1 for January, etc. Capitalization and spelling must be correct. If not a valid month, returns 0 ]] local function get_month_number (month) return cfg.date_names['local'].long[month] or cfg.date_names['local'].short[month] or -- look for local names first cfg.date_names['en'].long[month] or cfg.date_names['en'].short[month] or -- failing that, look for English names 0; -- not a recognized month name end --[[--------------------------< G E T _ S E A S O N _ N U M B E R >-------------------------------------------- returns a number according to the sequence of seasons in a year: 21 for Spring, etc. Capitalization and spelling must be correct. If not a valid season, returns 0. 21-24 = Spring, Summer, Autumn, Winter, independent of “Hemisphere” returns 0 when <param> is not |date= Season numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/) which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using numbers 21-41. cs1|2 only supports generic seasons. EDTF does support the distinction between north and south hemisphere seasons but cs1|2 has no way to make that distinction. These additional divisions not currently supported: 25-28 = Spring - Northern Hemisphere, Summer- Northern Hemisphere, Autumn - Northern Hemisphere, Winter - Northern Hemisphere 29-32 = Spring – Southern Hemisphere, Summer– Southern Hemisphere, Autumn – Southern Hemisphere, Winter - Southern Hemisphere 33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each) 37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each) 40-41 = Semestral 1, Semestral-2 (6 months each) ]] local function get_season_number (season, param) if 'date' ~= param then return 0; -- season dates only supported by |date= end return cfg.date_names['local'].season[season] or -- look for local names first cfg.date_names['en'].season[season] or -- failing that, look for English names 0; -- not a recognized season name end --[[--------------------------< G E T _ Q U A R T E R _ N U M B E R >------------------------------------------ returns a number according to the sequence of quarters in a year: 33 for first quarter, etc. Capitalization and spelling must be correct. If not a valid quarter, returns 0. 33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each) returns 0 when <param> is not |date= Quarter numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/) which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using numbers 21-41. cs1|2 only supports generic seasons and quarters. These additional divisions not currently supported: 37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each) 40-41 = Semestral 1, Semestral-2 (6 months each) ]] local function get_quarter_number (quarter, param) if 'date' ~= param then return 0; -- quarter dates only supported by |date= end quarter = mw.ustring.gsub (quarter, ' +', ' '); -- special case replace multiple space chars with a single space char return cfg.date_names['local'].quarter[quarter] or -- look for local names first cfg.date_names['en'].quarter[quarter] or -- failing that, look for English names 0; -- not a recognized quarter name end --[[--------------------------< G E T _ P R O P E R _ N A M E _ N U M B E R >---------------------------------- returns a non-zero number if date contains a recognized proper-name. Capitalization and spelling must be correct. returns 0 when <param> is not |date= ]] local function get_proper_name_number (name, param) if 'date' ~= param then return 0; -- proper-name dates only supported by |date= end return cfg.date_names['local'].named[name] or -- look for local names dates first cfg.date_names['en'].named[name] or -- failing that, look for English names 0; -- not a recognized named date end --[[--------------------------< G E T _ E L E M E N T _ N U M B E R <------------------------------------------ returns true if month or season or quarter or proper name is valid (properly spelled, capitalized, abbreviated) ]] local function get_element_number (element, param) local num; local funcs = {get_month_number, get_season_number, get_quarter_number, get_proper_name_number}; -- list of functions to execute in order for _, func in ipairs (funcs) do -- spin through the function list num = func (element, param); -- call the function and get the returned number if 0 ~= num then -- non-zero when valid month season quarter return num; -- return that number end end return nil; -- not valid end --[[--------------------------< I S _ V A L I D _ Y E A R >---------------------------------------------------- Function gets current year from the server and compares it to year from a citation parameter. Years more than one year in the future are not acceptable. Special case for |pmc-embargo-date=: years more than two years in the future are not acceptable ]] local function is_valid_year (year, param) if not is_set (year_limit) then year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once end year = tonumber (year) or lang_object:parseFormattedNumber (year); -- convert to number for the comparison; if 'pmc-embargo-date' == param then -- special case for |pmc-embargo-date= return year and (year <= tonumber(os.date("%Y"))+2) or false; -- years more than two years in the future are not accepted end return year and (year <= year_limit) or false; end --[[--------------------------< I S _ V A L I D _ D A T E >---------------------------------------------------- Returns true if day is less than or equal to the number of days in month and year is no farther into the future than next year; else returns false. Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately 1923) dates are assumed to be Gregorian. ]] local function is_valid_date (year, month, day, param) local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; local month_length; if not is_valid_year (year, param) then -- no farther into the future than next year except |pmc-embargo-date= no more than two years in the future return false; end month = tonumber (month); -- required for YYYY-MM-DD dates if (2 == month) then -- if February month_length = 28; -- then 28 days unless if 1582 > tonumber(year) then -- Julian calendar if 0 == (year%4) then -- is a leap year? month_length = 29; -- if leap year then 29 days in February end else -- Gregorian calendar if (0 == (year%4) and (0 ~= (year%100) or 0 == (year%400))) then -- is a leap year? month_length = 29; -- if leap year then 29 days in February end end else month_length = days_in_month[month]; end if tonumber (day) > month_length then return false; end return true; end --[[--------------------------< I S _ V A L I D _ M O N T H _ R A N G E _ S T Y L E >-------------------------- Months in a range are expected to have the same style: Jan–Mar or October–December but not February–Mar or Jul–August. This function looks in cfg.date_names{} to see if both month names are listed in the long subtable or both are listed in the short subtable. When both have the same style (both are listed in the same table), returns true; false else ]] local function is_valid_month_range_style (month1, month2) if (cfg.date_names.en.long[month1] and cfg.date_names.en.long[month2]) or -- are both English names listed in the long subtable? (cfg.date_names.en.short[month1] and cfg.date_names.en.short[month2]) or -- are both English names listed in the short subtable? (cfg.date_names['local'].long[month1] and cfg.date_names['local'].long[month2]) or -- are both local names listed in the long subtable? (cfg.date_names['local'].short[month1] and cfg.date_names['local'].short[month2]) then -- are both local names listed in the short subtable? return true; end return false; -- names are mixed end --[[--------------------------< I S _ V A L I D _ M O N T H _ S E A S O N _ R A N G E >------------------------ Check a pair of months or seasons to see if both are valid members of a month or season pair. Month pairs are expected to be left to right, earliest to latest in time. All season ranges are accepted as valid because there are publishers out there who have published a Summer–Spring YYYY issue, hence treat as ok ]] local function is_valid_month_season_range(range_start, range_end, param) local range_start_number = get_month_number (range_start); local range_end_number; if 0 == range_start_number then -- is this a month range? range_start_number = get_season_number (range_start, param); -- not a month; is it a season? get start season number range_end_number = get_season_number (range_end, param); -- get end season number if (0 ~= range_start_number) and (0 ~= range_end_number) and (range_start_number ~= range_end_number) then return true; -- any season pairing is accepted except when both are the same end return false; -- range_start and/or range_end is not a season end -- here when range_start is a month range_end_number = get_month_number (range_end); -- get end month number if range_start_number < range_end_number and -- range_start is a month; does range_start precede range_end? is_valid_month_range_style (range_start, range_end) then -- do months have the same style? return true; -- proper order and same style end return false; -- range_start month number is greater than or equal to range end number; or range end isn't a month end --[[--------------------------< M A K E _ C O I N S _ D A T E >------------------------------------------------ This function receives a table of date parts for one or two dates and an empty table reference declared in Module:Citation/CS1. The function is called only for |date= parameters and only if the |date=<value> is determined to be a valid date format. The question of what to do with invalid date formats is not answered here. The date parts in the input table are converted to an ISO 8601 conforming date string: single whole dates: yyyy-mm-dd month and year dates: yyyy-mm year dates: yyyy ranges: yyyy-mm-dd/yyyy-mm-dd yyyy-mm/yyyy-mm yyyy/yyyy Dates in the Julian calendar are reduced to year or year/year so that we don't have to do calendar conversion from Julian to Proleptic Gregorian. The input table has: year, year2 – always present; if before 1582, ignore months and days if present month, month2 – 0 if not provided, 1-12 for months, 21-24 for seasons; 99 Christmas day, day2 – 0 if not provided, 1-31 for days the output table receives: rftdate: an ISO 8601 formatted date rftchron: a free-form version of the date, usually without year which is in rftdate (season ranges and proper-name dates) rftssn: one of four season keywords: winter, spring, summer, fall (lowercase) rftquarter: one of four values: 1, 2, 3, 4 ]] local function make_COinS_date (input, tCOinS_date) local date; -- one date or first date in a range local date2 = ''; -- end of range date -- start temporary Julian / Gregorian calendar uncertainty detection local year = tonumber(input.year); -- this temporary code to determine the extent of sources dated to the Julian/Gregorian local month = tonumber(input.month); -- interstice 1 October 1582 – 1 January 1926 local day = tonumber (input.day); if (0 ~= day) and -- day must have a value for this to be a whole date (((1582 == year) and (10 <= month) and (12 >= month)) or -- any whole 1582 date from 1 October to 31 December or ((1926 == year) and (1 == month) and (1 == input.day)) or -- 1 January 1926 or ((1582 < year) and (1925 >= year))) then -- any date 1 January 1583 – 31 December 1925 tCOinS_date.inter_cal_cat = true; -- set category flag true end -- end temporary Julian / Gregorian calendar uncertainty detection if 1582 > tonumber(input.year) or 20 < tonumber(input.month) then -- Julian calendar or season so &rft.date gets year only date = input.year; if 0 ~= input.year2 and input.year ~= input.year2 then -- if a range, only the second year portion when not the same as range start year date = string.format ('%.4d/%.4d', tonumber(input.year), tonumber(input.year2)) -- assemble the date range end if 20 < tonumber(input.month) then -- if season or proper-name date local season = {[24] = 'winter', [21] = 'spring', [22] = 'summer', [23] = 'fall', [33] = '1', [34] = '2', [35] = '3', [36] = '4', [98] = 'Easter', [99] = 'Christmas'}; -- seasons lowercase, no autumn; proper-names use title case if 0 == input.month2 then -- single season date if 40 < tonumber(input.month) then tCOinS_date.rftchron = season[input.month]; -- proper-name dates elseif 30 < tonumber(input.month) then tCOinS_date.rftquarter = season[input.month]; -- quarters else tCOinS_date.rftssn = season[input.month]; -- seasons end else -- season range with a second season specified if input.year ~= input.year2 then -- season year – season year range or season year–year tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this? if 0~= input.month2 then tCOinS_date.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2); end else -- season–season year range tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this? tCOinS_date.rftchron = season[input.month] .. '–' .. season[input.month2]; -- season–season year range end end end tCOinS_date.rftdate = date; return; -- done end if 0 ~= input.day then date = string.format ('%s-%.2d-%.2d', input.year, tonumber(input.month), tonumber(input.day)); -- whole date elseif 0 ~= input.month then date = string.format ('%s-%.2d', input.year, tonumber(input.month)); -- year and month else date = string.format ('%s', input.year); -- just year end if 0 ~= input.year2 then if 0 ~= input.day2 then date2 = string.format ('/%s-%.2d-%.2d', input.year2, tonumber(input.month2), tonumber(input.day2)); -- whole date elseif 0 ~= input.month2 then date2 = string.format ('/%s-%.2d', input.year2, tonumber(input.month2)); -- year and month else date2 = string.format ('/%s', input.year2); -- just year end end tCOinS_date.rftdate = date .. date2; -- date2 has the '/' separator return; end --[[--------------------------< P A T T E R N S >-------------------------------------------------------------- this is the list of patterns for date formats that this module recognizes. Approximately the first half of these patterns represent formats that might be reformatted into another format. Those that might be reformatted have 'indicator' letters that identify the content of the matching capture: 'd' (day), 'm' (month), 'a' (anchor year), 'y' (year); second day, month, year have a '2' suffix. These patterns are used for both date validation and for reformatting. This table should not be moved to ~/Configuration because changes to this table require changes to check_date() and to reformatter() and reformat_date() ]] local patterns = { -- year-initial numerical year-month-day ['ymd'] = {'^(%d%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'}, -- month-initial: month day, year ['Mdy'] = {'^(%D-) +([1-9]%d?), +((%d%d%d%d?)%a?)$', 'm', 'd', 'a', 'y'}, -- month-initial day range: month day–day, year; days are separated by endash ['Md-dy'] = {'^(%D-) +([1-9]%d?)[%-–]([1-9]%d?), +((%d%d%d%d)%a?)$', 'm', 'd', 'd2', 'a', 'y'}, -- day-initial: day month year ['dMy'] = {'^([1-9]%d?) +(%D-) +((%d%d%d%d?)%a?)$', 'd', 'm', 'a', 'y'}, -- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed; not supported at en.wiki -- ['yMd'] = {'^((%d%d%d%d?)%a?) +(%D-) +(%d%d?)$', 'a', 'y', 'm', 'd'}, -- day-range-initial: day–day month year; days are separated by endash ['d-dMy'] = {'^([1-9]%d?)[%-–]([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'd2', 'm', 'a', 'y'}, -- day initial month-day-range: day month - day month year; uses spaced endash ['dM-dMy'] = {'^([1-9]%d?) +(%D-) +[%-–] +([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'm', 'd2', 'm2', 'a', 'y'}, -- month initial month-day-range: month day – month day, year; uses spaced endash ['Md-Mdy'] = {'^(%D-) +([1-9]%d?) +[%-–] +(%D-) +([1-9]%d?), +((%d%d%d%d)%a?)$','m', 'd', 'm2', 'd2', 'a', 'y'}, -- day initial month-day-year-range: day month year - day month year; uses spaced endash ['dMy-dMy'] = {'^([1-9]%d?) +(%D-) +(%d%d%d%d) +[%-–] +([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'm', 'y', 'd2', 'm2', 'a', 'y2'}, -- month initial month-day-year-range: month day, year – month day, year; uses spaced endash ['Mdy-Mdy'] = {'^(%D-) +([1-9]%d?), +(%d%d%d%d) +[%-–] +(%D-) +([1-9]%d?), +((%d%d%d%d)%a?)$', 'm', 'd', 'y', 'm2', 'd2', 'a', 'y2'}, -- these date formats cannot be converted, per se, but month name can be rendered short or long -- month/season year - month/season year; separated by spaced endash ['My-My'] = {'^(%D-) +(%d%d%d%d) +[%-–] +(%D-) +((%d%d%d%d)%a?)$', 'm', 'y', 'm2', 'a', 'y2'}, -- month/season range year; months separated by endash ['M-My'] = {'^(%D-)[%-–](%D-) +((%d%d%d%d)%a?)$', 'm', 'm2', 'a', 'y'}, -- month/season year or proper-name year; quarter year when First Quarter YYYY etc. ['My'] = {'^([^%d–]-) +((%d%d%d%d)%a?)$', 'm', 'a', 'y'}, -- this way because endash is a member of %D; %D- will match January–March 2019 when it shouldn't -- these date formats cannot be converted ['Sy4-y2'] = {'^(%D-) +((%d%d)%d%d)[%-–]((%d%d)%a?)$'}, -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash ['Sy-y'] = {'^(%D-) +(%d%d%d%d)[%-–]((%d%d%d%d)%a?)$'}, -- special case Winter/Summer year-year; year separated with unspaced endash ['y-y'] = {'^(%d%d%d%d?)[%-–]((%d%d%d%d?)%a?)$'}, -- year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999 ['y4-y2'] = {'^((%d%d)%d%d)[%-–]((%d%d)%a?)$'}, -- year range: YYYY–YY; separated by unspaced endash ['y'] = {'^((%d%d%d%d?)%a?)$'}, -- year; here accept either YYY or YYYY } --[[--------------------------< I S _ V A L I D _ E M B A R G O _ D A T E >------------------------------------ returns true and date value if that value has proper dmy, mdy, ymd format. returns false and 9999 (embargoed forever) when date value is not proper format; assumes that when |pmc-embargo-date= is set, the editor intended to embargo a PMC but |pmc-embargo-date= does not hold a single date. ]] local function is_valid_embargo_date (v) if v:match (patterns['ymd'][1]) or -- ymd v:match (patterns['Mdy'][1]) or -- dmy v:match (patterns['dMy'][1]) then -- mdy return true, v; end return false, '9999'; -- if here not good date so return false and set embargo date to long time in future end --[[--------------------------< C H E C K _ D A T E >---------------------------------------------------------- Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only allowed range separator is endash. Additionally, check the date to see that it is a real date: no 31 in 30-day months; no 29 February when not a leap year. Months, both long-form and three character abbreviations, and seasons must be spelled correctly. Future years beyond next year are not allowed. If the date fails the format tests, this function returns false and does not return values for anchor_year and COinS_date. When this happens, the date parameter is (DEBUG: not?) used in the COinS metadata and the CITEREF identifier gets its year from the year parameter if present otherwise CITEREF does not get a date value. Inputs: date_string - date string from date-holding parameters (date, year, publication-date, access-date, pmc-embargo-date, archive-date, lay-date) Returns: false if date string is not a real date; else true, anchor_year, COinS_date anchor_year can be used in CITEREF anchors COinS_date is ISO 8601 format date; see make_COInS_date() ]] local function check_date (date_string, param, tCOinS_date) local year; -- assume that year2, months, and days are not used; local year2 = 0; -- second year in a year range local month = 0; local month2 = 0; -- second month in a month range local day = 0; local day2 = 0; -- second day in a day range local anchor_year; local coins_date; if date_string:match (patterns['ymd'][1]) then -- year-initial numerical year month day format year, month, day = date_string:match (patterns['ymd'][1]); if 12 < tonumber(month) or 1 > tonumber(month) or 1582 > tonumber(year) or 0 == tonumber(day) then return false; end -- month or day number not valid or not Gregorian calendar anchor_year = year; elseif mw.ustring.match(date_string, patterns['Mdy'][1]) then -- month-initial: month day, year month, day, anchor_year, year = mw.ustring.match(date_string, patterns['Mdy'][1]); month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months elseif mw.ustring.match(date_string, patterns['Md-dy'][1]) then -- month-initial day range: month day–day, year; days are separated by endash month, day, day2, anchor_year, year = mw.ustring.match(date_string, patterns['Md-dy'][1]); if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same; month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months month2=month; -- for metadata year2 = year; elseif mw.ustring.match(date_string, patterns['dMy'][1]) then -- day-initial: day month year day, month, anchor_year, year = mw.ustring.match(date_string, patterns['dMy'][1]); month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months --[[ NOT supported at en.wiki elseif mw.ustring.match(date_string, patterns['yMd'][1]) then -- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed anchor_year, year, month, day = mw.ustring.match(date_string, patterns['yMd'][1]); month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months -- end NOT supported at en.wiki ]] elseif mw.ustring.match(date_string, patterns['d-dMy'][1]) then -- day-range-initial: day–day month year; days are separated by endash day, day2, month, anchor_year, year = mw.ustring.match(date_string, patterns['d-dMy'][1]); if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same; month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months month2 = month; -- for metadata year2 = year; elseif mw.ustring.match(date_string, patterns['dM-dMy'][1]) then -- day initial month-day-range: day month - day month year; uses spaced endash day, month, day2, month2, anchor_year, year = mw.ustring.match(date_string, patterns['dM-dMy'][1]); if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end -- date range order is left to right: earlier to later; month = get_month_number (month); -- for metadata month2 = get_month_number (month2); year2 = year; elseif mw.ustring.match(date_string, patterns['Md-Mdy'][1]) then -- month initial month-day-range: month day – month day, year; uses spaced endash month, day, month2, day2, anchor_year, year = mw.ustring.match(date_string, patterns['Md-Mdy'][1]); if (not is_valid_month_season_range(month, month2, param)) or not is_valid_year(year) then return false; end month = get_month_number (month); -- for metadata month2 = get_month_number (month2); year2 = year; elseif mw.ustring.match(date_string, patterns['dMy-dMy'][1]) then -- day initial month-day-year-range: day month year - day month year; uses spaced endash day, month, year, day2, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns['dMy-dMy'][1]); if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style month = get_month_number (month); -- for metadata month2 = get_month_number (month2); if 0 == month or 0 == month2 then return false; end -- both must be valid elseif mw.ustring.match(date_string, patterns['Mdy-Mdy'][1]) then -- month initial month-day-year-range: month day, year – month day, year; uses spaced endash month, day, year, month2, day2, anchor_year, year2 = mw.ustring.match(date_string, patterns['Mdy-Mdy'][1]); if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style month = get_month_number (month); -- for metadata month2 = get_month_number(month2); if 0 == month or 0 == month2 then return false; end -- both must be valid elseif mw.ustring.match(date_string, patterns['Sy4-y2'][1]) then -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash local century; month, year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns['Sy4-y2'][1]); if 'Winter' ~= month and 'Summer' ~= month then return false end; -- 'month' can only be Winter or Summer anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years year2 = century..year2; -- add the century to year2 for comparisons if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later if not is_valid_year(year2) then return false; end -- no year farther in the future than next year month = get_season_number(month, param); elseif mw.ustring.match(date_string, patterns['Sy-y'][1]) then -- special case Winter/Summer year-year; year separated with unspaced endash month, year, anchor_year, year2 = mw.ustring.match(date_string, patterns['Sy-y'][1]); month = get_season_number (month, param); -- <month> can only be winter or summer; also for metadata if (month ~= cfg.date_names['en'].season['Winter']) and (month ~= cfg.date_names['en'].season['Summer']) then return false; -- not Summer or Winter; abandon end anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later if not is_valid_year(year2) then return false; end -- no year farther in the future than next year elseif mw.ustring.match(date_string, patterns['My-My'][1]) then -- month/season year - month/season year; separated by spaced endash month, year, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns['My-My'][1]); anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same if not is_valid_year(year2) then return false; end -- no year farther in the future than next year if 0 ~= get_month_number(month) and 0 ~= get_month_number(month2) and is_valid_month_range_style(month, month2) then -- both must be month year, same month style month = get_month_number(month); month2 = get_month_number(month2); elseif 0 ~= get_season_number(month, param) and 0 ~= get_season_number(month2, param) then -- both must be season year, not mixed month = get_season_number(month, param); month2 = get_season_number(month2, param); else return false; end elseif mw.ustring.match(date_string, patterns['M-My'][1]) then -- month/season range year; months separated by endash month, month2, anchor_year, year = mw.ustring.match(date_string, patterns['M-My'][1]); if (not is_valid_month_season_range(month, month2, param)) or (not is_valid_year(year)) then return false; end if 0 ~= get_month_number(month) then -- determined to be a valid range so just check this one to know if month or season month = get_month_number(month); month2 = get_month_number(month2); if 0 == month or 0 == month2 then return false; end else month = get_season_number(month, param); month2 = get_season_number(month2, param); end year2 = year; elseif mw.ustring.match(date_string, patterns['My'][1]) then -- month/season/quarter/proper-name year month, anchor_year, year = mw.ustring.match(date_string, patterns['My'][1]); if not is_valid_year(year) then return false; end month = get_element_number(month, param); -- get month season quarter proper-name number or nil if not month then return false; end -- not valid whatever it is elseif mw.ustring.match(date_string, patterns['y-y'][1]) then -- Year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999 year, anchor_year, year2 = mw.ustring.match(date_string, patterns['y-y'][1]); anchor_year = year .. '–' .. anchor_year; -- assemble anchor year from both years if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same if not is_valid_year(year2) then return false; end -- no year farther in the future than next year elseif mw.ustring.match(date_string, patterns['y4-y2'][1]) then -- Year range: YYYY–YY; separated by unspaced endash local century; year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns['y4-y2'][1]); anchor_year = year .. '–' .. anchor_year; -- assemble anchor year from both years if in_array (param, {'date', 'publication-date', 'year'}) then add_prop_cat ('year-range-abbreviated'); end if 13 > tonumber(year2) then return false; end -- don't allow 2003-05 which might be May 2003 year2 = century .. year2; -- add the century to year2 for comparisons if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same if not is_valid_year(year2) then return false; end -- no year farther in the future than next year elseif mw.ustring.match(date_string, patterns['y'][1]) then -- year; here accept either YYY or YYYY anchor_year, year = mw.ustring.match(date_string, patterns['y'][1]); if false == is_valid_year(year) then return false; end else return false; -- date format not one of the MOS:DATE approved formats end if 'access-date' == param then -- test accessdate here because we have numerical date parts if 0 ~= year and 0 ~= month and 0 ~= day and -- all parts of a single date required 0 == year2 and 0 == month2 and 0 == day2 then -- none of these; accessdate must not be a range if not is_valid_accessdate(year .. '-' .. month .. '-' .. day) then return false; -- return false when accessdate out of bounds end else return false; -- return false when accessdate is a range of two dates end end local result=true; -- check whole dates for validity; assume true because not all dates will go through this test if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then -- YMD (simple whole date) result = is_valid_date (year, month, day, param); -- <param> for |pmc-embargo-date= elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 ~= day2 then -- YMD-d (day range) result = is_valid_date (year, month, day); result = result and is_valid_date (year, month, day2); elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-md (day month range) result = is_valid_date (year, month, day); result = result and is_valid_date (year, month2, day2); elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 ~= year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-ymd (day month year range) result = is_valid_date(year, month, day); result = result and is_valid_date(year2, month2, day2); end if false == result then return false; end if nil ~= tCOinS_date then -- this table only passed into this function when testing |date= parameter values make_COinS_date ({year = year, month = month, day = day, year2 = year2, month2 = month2, day2 = day2}, tCOinS_date); -- make an ISO 8601 date string for COinS end return true, anchor_year; -- format is good and date string represents a real date end --[[--------------------------< D A T E S >-------------------------------------------------------------------- Cycle the date-holding parameters in passed table date_parameters_list through check_date() to check compliance with MOS:DATE. For all valid dates, check_date() returns true. The |date= parameter test is unique, it is the only date holding parameter from which values for anchor_year (used in CITEREF identifiers) and COinS_date (used in the COinS metadata) are derived. The |date= parameter is the only date-holding parameter that is allowed to contain the no-date keywords "n.d." or "nd" (without quotes). Unlike most error messages created in this module, only one error message is created by this function. Because all of the date holding parameters are processed serially, parameters with errors are added to the <error_list> sequence table as the dates are tested. ]] local function dates(date_parameters_list, tCOinS_date, error_list) local anchor_year; -- will return as nil if the date being tested is not |date= local COinS_date; -- will return as nil if the date being tested is not |date= local embargo_date; -- if embargo date is a good dmy, mdy, ymd date then holds original value else reset to 9999 local good_date = false; for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list if is_set(v.val) then -- if the parameter has a value v.val = mw.ustring.gsub(v.val, '%d', cfg.date_names.local_digits); -- translate 'local' digits to Western 0-9 if v.val:match("^c%. [1-9]%d%d%d?%a?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year= local year = v.val:match("c%. ([1-9]%d%d%d?)%a?"); -- get the year portion so it can be tested if 'date' == k then anchor_year, COinS_date = v.val:match("((c%. [1-9]%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter good_date = is_valid_year(year); elseif 'year' == k then good_date = is_valid_year(year); end elseif 'date' == k then -- if the parameter is |date= if v.val:match("^n%.d%.%a?$") then -- ToDo: I18N -- if |date=n.d. with or without a CITEREF disambiguator good_date, anchor_year, COinS_date = true, v.val:match("((n%.d%.)%a?)"); -- ToDo: I18N -- "n.d."; no error when date parameter is set to no date elseif v.val:match("^nd%a?$") then -- ToDo: I18N -- if |date=nd with or without a CITEREF disambiguator good_date, anchor_year, COinS_date = true, v.val:match("((nd)%a?)"); -- ToDo: I18N -- "nd"; no error when date parameter is set to no date else good_date, anchor_year, COinS_date = check_date (v.val, k, tCOinS_date); -- go test the date end elseif 'year' == k then -- if the parameter is |year= it should hold only a year value if v.val:match("^[1-9]%d%d%d?%a?$") then -- if |year = 3 or 4 digits only with or without a CITEREF disambiguator good_date, anchor_year, COinS_date = true, v.val:match("((%d+)%a?)"); end elseif 'pmc-embargo-date' == k then -- if the parameter is |pmc-embargo-date= good_date = check_date (v.val, k); -- go test the date if true == good_date then -- if the date is a valid date good_date, embargo_date = is_valid_embargo_date (v.val); -- is |pmc-embargo-date= date a single dmy, mdy, or ymd formatted date? yes: returns embargo date; no: returns 9999 end else -- any other date-holding parameter good_date = check_date (v.val, k); -- go test the date end if false == good_date then -- assemble one error message so we don't add the tracking category multiple times table.insert (error_list, wrap_style ('parameter', v.name)); -- make parameter name suitable for error message list end end end return anchor_year, embargo_date; -- and done end --[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------ Compare the value provided in |year= with the year value(s) provided in |date=. This function sets a local numeric value: 0 - year value does not match the year value in date 1 - (default) year value matches the year value in date or one of the year values when date contains two years 2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx) the numeric value in <result> determines the 'output' if any from this function: 0 – adds error message to error_list sequence table 1 – adds maint cat 2 – does nothing ]] local function year_date_check (year_string, year_origin, date_string, date_origin, error_list) local year; local date1; local date2; local result = 1; -- result of the test; assume that the test passes year = year_string:match ('(%d%d%d%d?)'); if date_string:match ('%d%d%d%d%-%d%d%-%d%d') and year_string:match ('%d%d%d%d%a') then --special case where both date and year are required YYYY-MM-DD and YYYYx date1 = date_string:match ('(%d%d%d%d)'); year = year_string:match ('(%d%d%d%d)'); if year ~= date1 then result = 0; -- years don't match else result = 2; -- years match; but because disambiguated, don't add to maint cat end elseif date_string:match ("%d%d%d%d?.-%d%d%d%d?") then -- any of the standard range formats of date with two three- or four-digit years date1, date2 = date_string:match ("(%d%d%d%d?).-(%d%d%d%d?)"); if year ~= date1 and year ~= date2 then result = 0; end elseif mw.ustring.match(date_string, "%d%d%d%d[%-–]%d%d") then -- YYYY-YY date ranges local century; date1, century, date2 = mw.ustring.match(date_string, "((%d%d)%d%d)[%-–]+(%d%d)"); date2 = century..date2; -- convert YY to YYYY if year ~= date1 and year ~= date2 then result = 0; end elseif date_string:match ("%d%d%d%d?") then -- any of the standard formats of date with one year date1 = date_string:match ("(%d%d%d%d?)"); if year ~= date1 then result = 0; end else -- should never get here; this function called only when no other date errors result = 0; -- no recognizable year in date end if 0 == result then -- year / date mismatch table.insert (error_list, substitute (cfg.messages['mismatch'], {year_origin, date_origin})); -- add error message to error_list sequence table elseif 1 == result then -- redundant year / date set_message ('maint_date_year'); -- add a maint cat end end --[[--------------------------< R E F O R M A T T E R >-------------------------------------------------------- reformat 'date' into new format specified by format_param if pattern_idx (the current format of 'date') can be reformatted. Does the grunt work for reformat_dates(). The table re_formats maps pattern_idx (current format) and format_param (desired format) to a table that holds: format string used by string.format() identifier letters ('d', 'm', 'y', 'd2', 'm2', 'y2') that serve as indexes into a table t{} that holds captures from mw.ustring.match() for the various date parts specified by patterns[pattern_idx][1] Items in patterns{} have the general form: ['ymd'] = {'^(%d%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'}, where: ['ymd'] is pattern_idx patterns['ymd'][1] is the match pattern with captures for mw.ustring.match() patterns['ymd'][2] is an indicator letter identifying the content of the first capture patterns['ymd'][3] ... the second capture etc. when a pattern matches a date, the captures are loaded into table t{} in capture order using the idemtifier characters as indexes into t{} For the above, a ymd date is in t{} as: t.y = first capture (year), t.m = second capture (month), t.d = third capture (day) To reformat, this function is called with the pattern_idx that matches the current format of the date and with format_param set to the desired format. This function loads table t{} as described and then calls string.format() with the format string specified by re_format[pattern_idx][format_param][1] using values taken from t{} according to the capture identifier letters specified by patterns[pattern_idx][format_param][n] where n is 2.. ]] local re_formats = { ['ymd'] = { -- date format is ymd; reformat to: ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy -- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki }, ['Mdy'] = { -- date format is Mdy; reformat to: ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- for long/short reformatting ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy ['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd -- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki }, ['dMy'] = { -- date format is dMy; reformat to: ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- for long/short reformatting ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy ['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd -- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki }, ['Md-dy'] = { -- date format is Md-dy; reformat to: ['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'}, -- for long/short reformatting ['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'}, -- |df=dmy -> d-dMy }, ['d-dMy'] = { -- date format is d-d>y; reformat to: ['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'}, -- for long/short reformatting ['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'}, -- |df=mdy -> Md-dy }, ['dM-dMy'] = { -- date format is dM-dMy; reformat to: ['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'}, -- for long/short reformatting ['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'}, -- |df=mdy -> Md-Mdy }, ['Md-Mdy'] = { -- date format is Md-Mdy; reformat to: ['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'}, -- for long/short reformatting ['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'}, -- |df=dmy -> dM-dMy }, ['dMy-dMy'] = { -- date format is dMy-dMy; reformat to: ['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'}, -- for long/short reformatting ['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'}, -- |df=mdy -> Mdy-Mdy }, ['Mdy-Mdy'] = { -- date format is Mdy-Mdy; reformat to: ['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'}, -- for long/short reformatting ['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'}, -- |df=dmy -> dMy-dMy }, ['My-My'] = { -- these for long/short reformatting ['any'] = {'%s %s – %s %s', 'm', 'y', 'm2', 'y2'}, -- dmy/mdy agnostic }, ['M-My'] = { -- these for long/short reformatting ['any'] = {'%s–%s %s', 'm', 'm2', 'y'}, -- dmy/mdy agnostic }, ['My'] = { -- these for long/short reformatting ['any'] = {'%s %s', 'm', 'y'}, -- dmy/mdy agnostic }, -- ['yMd'] = { -- not supported at en.wiki -- ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy -- ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy -- ['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd -- }, } local function reformatter (date, pattern_idx, format_param, mon_len) if not in_array (pattern_idx, {'ymd', 'Mdy', 'Md-dy', 'dMy', 'yMd', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) then return; -- not in this set of date format patterns then not a reformattable date end if 'ymd' == format_param and in_array (pattern_idx, {'ymd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) then return; -- ymd date ranges not supported at en.wiki; no point in reformatting ymd to ymd end if in_array (pattern_idx, {'My', 'M-My', 'My-My'}) then -- these are not dmy/mdy so can't be 'reformatted' into either format_param = 'any'; -- so format-agnostic end -- yMd is not supported at en.wiki; when yMd is supported at your wiki, uncomment the next line -- if 'yMd' == format_param and in_array (pattern_idx, {'yMd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy'}) then -- these formats not convertable; yMd not supported at en.wiki if 'yMd' == format_param then -- yMd not supported at en.wiki; when yMd is supported at your wiki, remove or comment-out this line return; -- not a reformattable date end local c1, c2, c3, c4, c5, c6, c7; -- these hold the captures specified in patterns[pattern_idx][1] c1, c2, c3, c4, c5, c6, c7 = mw.ustring.match (date, patterns[pattern_idx][1]); -- get the captures local t = { -- table that holds k/v pairs of date parts from the captures and patterns[pattern_idx][2..] [patterns[pattern_idx][2]] = c1; -- at minimum there is always one capture with a matching indicator letter [patterns[pattern_idx][3] or 'x'] = c2; -- patterns can have a variable number of captures; each capture requires an indicator letter; [patterns[pattern_idx][4] or 'x'] = c3; -- where there is no capture, there is no indicator letter so n in patterns[pattern_idx][n] will be nil; [patterns[pattern_idx][5] or 'x'] = c4; -- the 'x' here spoofs an indicator letter to prevent 'table index is nil' error [patterns[pattern_idx][6] or 'x'] = c5; [patterns[pattern_idx][7] or 'x'] = c6; [patterns[pattern_idx][8] or 'x'] = c7; }; if t.a then -- if this date has an anchor year capture (all convertable date formats except ymd) if t.y2 then -- for year range date formats t.y2 = t.a; -- use the anchor year capture when reassembling the date else -- here for single date formats (except ymd) t.y = t.a; -- use the anchor year capture when reassembling the date end end if tonumber(t.m) then -- if raw month is a number (converting from ymd) if 's' == mon_len then -- if we are to use abbreviated month names t.m = cfg.date_names['inv_local_short'][tonumber(t.m)]; -- convert it to a month name else t.m = cfg.date_names['inv_local_long'][tonumber(t.m)]; -- convert it to a month name end t.d = t.d:gsub ('0(%d)', '%1'); -- strip leading '0' from day if present elseif 'ymd' == format_param then -- when converting to ymd t.y = t.y:gsub ('%a', ''); -- strip CITREF disambiguator if present; anchor year already known so process can proceed; TODO: maint message? if 1582 > tonumber (t.y) then -- ymd format dates not allowed before 1582 return; end t.m = string.format ('%02d', get_month_number (t.m)); -- make sure that month and day are two digits t.d = string.format ('%02d', t.d); elseif mon_len then -- if mon_len is set to either 'short' or 'long' for _, mon in ipairs ({'m', 'm2'}) do -- because there can be two month names, check both if t[mon] then t[mon] = get_month_number (t[mon]); -- get the month number for this month (is length agnostic) if 0 == t[mon] then return; end -- seasons and named dates can't be converted t[mon] = (('s' == mon_len) and cfg.date_names['inv_local_short'][t[mon]]) or cfg.date_names['inv_local_long'][t[mon]]; -- fetch month name according to length end end end local new_date = string.format (re_formats[pattern_idx][format_param][1], -- format string t[re_formats[pattern_idx][format_param][2]], -- named captures from t{} t[re_formats[pattern_idx][format_param][3]], t[re_formats[pattern_idx][format_param][4]], t[re_formats[pattern_idx][format_param][5]], t[re_formats[pattern_idx][format_param][6]], t[re_formats[pattern_idx][format_param][7]], t[re_formats[pattern_idx][format_param][8]] ); return new_date; end --[[-------------------------< R E F O R M A T _ D A T E S >-------------------------------------------------- Reformats existing dates into the format specified by format. format is one of several manual keywords: dmy, dmy-all, mdy, mdy-all, ymd, ymd-all. The -all version includes access- and archive-dates; otherwise these dates are not reformatted. This function allows automatic date formatting. In ~/Configuration, the article source is searched for one of the {{use xxx dates}} templates. If found, xxx becomes the global date format as xxx-all. If |cs1-dates= in {{use xxx dates}} has legitimate value then that value determines how cs1|2 dates will be rendered. Legitimate values for |cs1-dates= are: l - all dates are rendered with long month names ls - publication dates use long month names; access-/archive-dates use abbreviated month names ly - publication dates use long month names; access-/archive-dates rendered in ymd format s - all dates are rendered with abbreviated (short) month names sy - publication dates use abbreviated month names; access-/archive-dates rendered in ymd format y - all dates are rendered in ymd format the format argument for automatic date formatting will be the format specified by {{use xxx dates}} with the value supplied by |cs1-dates so one of: xxx-l, xxx-ls, xxx-ly, xxx-s, xxx-sy, xxx-y, or simply xxx (|cs1-dates= empty, omitted, or invalid) where xxx shall be either of dmy or mdy. dates are extracted from date_parameters_list, reformatted (if appropriate), and then written back into the list in the new format. Dates in date_parameters_list are presumed here to be valid (no errors). This function returns true when a date has been reformatted, false else. Actual reformatting is done by reformatter(). ]] local function reformat_dates (date_parameters_list, format) local all = false; -- set to false to skip access- and archive-dates local len_p = 'l'; -- default publication date length shall be long local len_a = 'l'; -- default access-/archive-date length shall be long local result = false; local new_date; if format:match('%a+%-all') then -- manual df keyword; auto df keyword when length not specified in {{use xxx dates}}; format = format:match('(%a+)%-all'); -- extract the format all = true; -- all dates are long format dates because this keyword doesn't specify length elseif format:match('%a+%-[lsy][sy]?') then -- auto df keywords; internal only all = true; -- auto df applies to all dates; use length specified by capture len_p for all dates format, len_p, len_a = format:match('(%a+)%-([lsy])([sy]?)'); -- extract the format and length keywords if 'y' == len_p then -- because allowed by MOS:DATEUNIFY (sort of) range dates and My dates not reformatted format = 'ymd'; -- override {{use xxx dates}} elseif (not is_set(len_a)) or (len_p == len_a) then -- no access-/archive-date length specified or same length as publication dates then len_a = len_p; -- in case len_a not set end end -- else only publication dates and they are long for param_name, param_val in pairs (date_parameters_list) do -- for each date-holding parameter in the list if is_set (param_val.val) then -- if the parameter has a value if not (not all and in_array (param_name, {'access-date', 'archive-date'})) then -- skip access- or archive-date unless format is xxx-all; yeah, ugly; TODO: find a better way for pattern_idx, pattern in pairs (patterns) do if mw.ustring.match (param_val.val, pattern[1]) then if all and in_array (param_name, {'access-date', 'archive-date'}) then -- if this date is an access- or archive-date new_date = reformatter (param_val.val, pattern_idx, (('y' == len_a) and 'ymd') or format, len_a); -- choose ymd or dmy/mdy according to len_a setting else -- all other dates new_date = reformatter (param_val.val, pattern_idx, format, len_p); end if new_date then -- set when date was reformatted date_parameters_list[param_name].val = new_date; -- update date in date list result = true; -- and announce that changes have been made end end -- if end -- for end -- if end -- if end -- for return result; -- declare boolean result and done end --[[--------------------------< D A T E _ H Y P H E N _ T O _ D A S H >---------------------------------------- Loops through the list of date-holding parameters and converts any hyphen to an ndash. Not called if the cs1|2 template has any date errors. Modifies the date_parameters_list and returns true if hyphens are replaced, else returns false. ]] local function date_hyphen_to_dash (date_parameters_list) local result = false; local n; for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list if is_set (param_val.val) and not mw.ustring.match (param_val.val, patterns.ymd[1]) then -- for those that are not ymd dates (ustring because here digits may not be Western) param_val.val, n = param_val.val:gsub ('%-', '–'); -- replace any hyphen with ndash if 0 ~= n then date_parameters_list[param_name].val = param_val.val; -- update the list result = true; end end end return result; -- so we know if any hyphens were replaced end --[[-------------------------< D A T E _ N A M E _ X L A T E >------------------------------------------------ Attempts to translate English date names to local-language date names using names supplied by MediaWiki's date parser function. This is simple name-for-name replacement and may not work for all languages. if xlat_dig is true, this function will also translate Western (English) digits to the local language's digits. This will also translate ymd dates. ]] local function date_name_xlate (date_parameters_list, xlt_dig) local xlate; local mode; -- long or short month names local modified = false; local date; local sources_t = { {cfg.date_names.en.long, cfg.date_names.inv_local_long}, -- for translating long English month names to long local month names {cfg.date_names.en.short, cfg.date_names.inv_local_short}, -- short month names {cfg.date_names.en.quarter, cfg.date_names.inv_local_quarter}, -- quarter date names {cfg.date_names.en.season, cfg.date_names.inv_local_season}, -- season date nam {cfg.date_names.en.named, cfg.date_names.inv_local_named}, -- named dates } local function is_xlateable (month) -- local function to get local date name that replaces existing English-language date name for _, date_names_t in ipairs (sources_t) do -- for each sequence table in date_names_t if date_names_t[1][month] then -- if date name is English month (long or short), quarter, season or named and if date_names_t[2][date_names_t[1][month]] then -- if there is a matching local date name return date_names_t[2][date_names_t[1][month]]; -- return the local date name end end end end for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list if is_set(param_val.val) then -- if the parameter has a value date = param_val.val; for month in mw.ustring.gmatch (date, '[%a ]+') do -- iterate through all date names in the date (single date or date range) month = mw.text.trim (month); -- this because quarterly dates contain whitespace xlate = is_xlateable (month); -- get translate <month>; returns translation or nil -- if cfg.date_names.en.long[month] then -- long month dates -- if cfg.date_names.inv_local_long[cfg.date_names.en.long[month]] then -- xlate = cfg.date_names.inv_local_long[cfg.date_names.en.long[month]]; -- end ---- mode = 'F'; -- English name is long so use long local name -- elseif cfg.date_names.en.short[month] then -- short month dates -- if cfg.date_names.inv_local_short[cfg.date_names.en.short[month]] then -- xlate = cfg.date_names.inv_local_short[cfg.date_names.en.short[month]]; -- end ---- mode = 'M'; -- English name is short so use short local name -- elseif cfg.date_names.en.quarter[month] then -- quarter dates -- if cfg.date_names.inv_local_quarter[cfg.date_names.en.quarter[month]] then -- xlate = cfg.date_names.inv_local_quarter[cfg.date_names.en.quarter[month]]; -- end -- elseif cfg.date_names.en.season[month] then -- season dates -- if cfg.date_names.inv_local_season[cfg.date_names.en.season[month]] then -- xlate = cfg.date_names.inv_local_season[cfg.date_names.en.season[month]]; -- end -- elseif cfg.date_names.en.named[month] then -- named dates -- if cfg.date_names.inv_local_named[cfg.date_names.en.named[month]] then -- xlate = cfg.date_names.inv_local_named[cfg.date_names.en.named[month]]; -- end -- else -- xlate=nil; -- not an English month name; could be local language month name ---- mode = nil; -- not an English month name; could be local language month name or an English season name -- end if xlate then -- if mode then -- might be a season -- xlate = lang_object:formatDate(mode, '1' .. month); -- translate the month name to this local language date = mw.ustring.gsub (date, month, xlate); -- replace the English with the translation date_parameters_list[param_name].val = date; -- save the translated date modified = true; end end if xlt_dig then -- shall we also translate digits? date = date:gsub ('%d', cfg.date_names.xlate_digits); -- translate digits from Western to 'local digits' date_parameters_list[param_name].val = date; -- save the translated date modified = true; end end end return modified; end --[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >-------------------------------------- Sets local imported functions table to same (live or sandbox) as that used by the other modules. ]] local function set_selected_modules (cfg_table_ptr, utilities_page_ptr) add_prop_cat = utilities_page_ptr.add_prop_cat ; -- import functions from selected Module:Citation/CS1/Utilities module is_set = utilities_page_ptr.is_set; in_array = utilities_page_ptr.in_array; set_message = utilities_page_ptr.set_message; substitute = utilities_page_ptr.substitute; wrap_style = utilities_page_ptr.wrap_style; cfg = cfg_table_ptr; -- import tables from selected Module:Citation/CS1/Configuration end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { -- return exported functions dates = dates, year_date_check = year_date_check, reformat_dates = reformat_dates, date_hyphen_to_dash = date_hyphen_to_dash, date_name_xlate = date_name_xlate, set_selected_modules = set_selected_modules } d0271b200019639fd12f2b6c5e53be0e844e8453 Module:Citation/CS1 828 50 115 2022-07-01T17:45:25Z Canopus >Trappist the monk 0 sync from sandbox; Scribunto text/plain require ('Module:No globals'); --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- each of these counts against the Lua upvalue limit ]] local validation; -- functions in Module:Citation/CS1/Date_validation local utilities; -- functions in Module:Citation/CS1/Utilities local z ={}; -- table of tables in Module:Citation/CS1/Utilities local identifiers; -- functions and tables in Module:Citation/CS1/Identifiers local metadata; -- functions in Module:Citation/CS1/COinS local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist --[[------------------< P A G E S C O P E V A R I A B L E S >--------------- declare variables here that have page-wide scope that are not brought in from other modules; that are created here and used here ]] local added_deprecated_cat; -- Boolean flag so that the category is added only once local added_vanc_errs; -- Boolean flag so we only emit one Vancouver error / category local added_generic_name_errs; -- Boolean flag so we only emit one generic name error / category and stop testing names once an error is encountered local Frame; -- holds the module's frame table local is_preview_mode; -- true when article is in preview mode; false when using 'Preview page with this template' (previewing the module) local is_sandbox; -- true when using sandbox modules to render citation --[[--------------------------< F I R S T _ S E T >------------------------------------------------------------ Locates and returns the first set value in a table of values where the order established in the table, left-to-right (or top-to-bottom), is the order in which the values are evaluated. Returns nil if none are set. This version replaces the original 'for _, val in pairs do' and a similar version that used ipairs. With the pairs version the order of evaluation could not be guaranteed. With the ipairs version, a nil value would terminate the for-loop before it reached the actual end of the list. ]] local function first_set (list, count) local i = 1; while i <= count do -- loop through all items in list if utilities.is_set( list[i] ) then return list[i]; -- return the first set list member end i = i + 1; -- point to next end end --[[--------------------------< A D D _ V A N C _ E R R O R >---------------------------------------------------- Adds a single Vancouver system error message to the template's output regardless of how many error actually exist. To prevent duplication, added_vanc_errs is nil until an error message is emitted. added_vanc_errs is a Boolean declared in page scope variables above ]] local function add_vanc_error (source, position) if added_vanc_errs then return end added_vanc_errs = true; -- note that we've added this category utilities.set_message ('err_vancouver', {source, position}); end --[[--------------------------< I S _ S C H E M E >------------------------------------------------------------ does this thing that purports to be a URI scheme seem to be a valid scheme? The scheme is checked to see if it is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says: Scheme names consist of a sequence of characters beginning with a letter and followed by any combination of letters, digits, plus ("+"), period ("."), or hyphen ("-"). returns true if it does, else false ]] local function is_scheme (scheme) return scheme and scheme:match ('^%a[%a%d%+%.%-]*:'); -- true if scheme is set and matches the pattern end --[=[-------------------------< I S _ D O M A I N _ N A M E >-------------------------------------------------- Does this thing that purports to be a domain name seem to be a valid domain name? Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5 BNF defined here: https://tools.ietf.org/html/rfc4234 Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15; see also [[Single-letter second-level domain]] list of TLDs: https://www.iana.org/domains/root/db RFC 952 (modified by RFC 1123) requires the first and last character of a hostname to be a letter or a digit. Between the first and last characters the name may use letters, digits, and the hyphen. Also allowed are IPv4 addresses. IPv6 not supported domain is expected to be stripped of any path so that the last character in the last character of the TLD. tld is two or more alpha characters. Any preceding '//' (from splitting a URL with a scheme) will be stripped here. Perhaps not necessary but retained in case it is necessary for IPv4 dot decimal. There are several tests: the first character of the whole domain name including subdomains must be a letter or a digit internationalized domain name (ASCII characters with .xn-- ASCII Compatible Encoding (ACE) prefix xn-- in the TLD) see https://tools.ietf.org/html/rfc3490 single-letter/digit second-level domains in the .org, .cash, and .today TLDs q, x, and z SL domains in the .com TLD i and q SL domains in the .net TLD single-letter SL domains in the ccTLDs (where the ccTLD is two letters) two-character SL domains in gTLDs (where the gTLD is two or more letters) three-plus-character SL domains in gTLDs (where the gTLD is two or more letters) IPv4 dot-decimal address format; TLD not allowed returns true if domain appears to be a proper name and TLD or IPv4 address, else false ]=] local function is_domain_name (domain) if not domain then return false; -- if not set, abandon end domain = domain:gsub ('^//', ''); -- strip '//' from domain name if present; done here so we only have to do it once if not domain:match ('^[%w]') then -- first character must be letter or digit return false; end if domain:match ('^%a+:') then -- hack to detect things that look like s:Page:Title where Page: is namespace at Wikisource return false; end local patterns = { -- patterns that look like URLs '%f[%w][%w][%w%-]+[%w]%.%a%a+$', -- three or more character hostname.hostname or hostname.tld '%f[%w][%w][%w%-]+[%w]%.xn%-%-[%w]+$', -- internationalized domain name with ACE prefix '%f[%a][qxz]%.com$', -- assigned one character .com hostname (x.com times out 2015-12-10) '%f[%a][iq]%.net$', -- assigned one character .net hostname (q.net registered but not active 2015-12-10) '%f[%w][%w]%.%a%a$', -- one character hostname and ccTLD (2 chars) '%f[%w][%w][%w]%.%a%a+$', -- two character hostname and TLD '^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?', -- IPv4 address } for _, pattern in ipairs (patterns) do -- loop through the patterns list if domain:match (pattern) then return true; -- if a match then we think that this thing that purports to be a URL is a URL end end for _, d in ipairs ({'cash', 'company', 'today', 'org'}) do -- look for single letter second level domain names for these top level domains if domain:match ('%f[%w][%w]%.' .. d) then return true end end return false; -- no matches, we don't know what this thing is end --[[--------------------------< I S _ U R L >------------------------------------------------------------------ returns true if the scheme and domain parts of a URL appear to be a valid URL; else false. This function is the last step in the validation process. This function is separate because there are cases that are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external wikilinks. ]] local function is_url (scheme, domain) if utilities.is_set (scheme) then -- if scheme is set check it and domain return is_scheme (scheme) and is_domain_name (domain); else return is_domain_name (domain); -- scheme not set when URL is protocol-relative end end --[[--------------------------< S P L I T _ U R L >------------------------------------------------------------ Split a URL into a scheme, authority indicator, and domain. First remove Fully Qualified Domain Name terminator (a dot following TLD) (if any) and any path(/), query(?) or fragment(#). If protocol-relative URL, return nil scheme and domain else return nil for both scheme and domain. When not protocol-relative, get scheme, authority indicator, and domain. If there is an authority indicator (one or more '/' characters immediately following the scheme's colon), make sure that there are only 2. Any URL that does not have news: scheme must have authority indicator (//). TODO: are there other common schemes like news: that don't use authority indicator? Strip off any port and path; ]] local function split_url (url_str) local scheme, authority, domain; url_str = url_str:gsub ('([%a%d])%.?[/%?#].*$', '%1'); -- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of '//') if url_str:match ('^//%S*') then -- if there is what appears to be a protocol-relative URL domain = url_str:match ('^//(%S*)') elseif url_str:match ('%S-:/*%S+') then -- if there is what appears to be a scheme, optional authority indicator, and domain name scheme, authority, domain = url_str:match ('(%S-:)(/*)(%S+)'); -- extract the scheme, authority indicator, and domain portions if utilities.is_set (authority) then authority = authority:gsub ('//', '', 1); -- replace place 1 pair of '/' with nothing; if utilities.is_set(authority) then -- if anything left (1 or 3+ '/' where authority should be) then return scheme; -- return scheme only making domain nil which will cause an error message end else if not scheme:match ('^news:') then -- except for news:..., MediaWiki won't link URLs that do not have authority indicator; TODO: a better way to do this test? return scheme; -- return scheme only making domain nil which will cause an error message end end domain = domain:gsub ('(%a):%d+', '%1'); -- strip port number if present end return scheme, domain; end --[[--------------------------< L I N K _ P A R A M _ O K >--------------------------------------------------- checks the content of |title-link=, |series-link=, |author-link=, etc. for properly formatted content: no wikilinks, no URLs Link parameters are to hold the title of a Wikipedia article, so none of the WP:TITLESPECIALCHARACTERS are allowed: # < > [ ] | { } _ except the underscore which is used as a space in wiki URLs and # which is used for section links returns false when the value contains any of these characters. When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid URL (the |<param>-link= parameter is ok); else false when value appears to be a valid URL (the |<param>-link= parameter is NOT ok). ]] local function link_param_ok (value) local scheme, domain; if value:find ('[<>%[%]|{}]') then -- if any prohibited characters return false; end scheme, domain = split_url (value); -- get scheme or nil and domain or nil from URL; return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid URL end --[[--------------------------< L I N K _ T I T L E _ O K >--------------------------------------------------- Use link_param_ok() to validate |<param>-link= value and its matching |<title>= value. |<title>= may be wiki-linked but not when |<param>-link= has a value. This function emits an error message when that condition exists check <link> for inter-language interwiki-link prefix. prefix must be a MediaWiki-recognized language code and must begin with a colon. ]] local function link_title_ok (link, lorig, title, torig) local orig; if utilities.is_set (link) then -- don't bother if <param>-link doesn't have a value if not link_param_ok (link) then -- check |<param>-link= markup orig = lorig; -- identify the failing link parameter elseif title:find ('%[%[') then -- check |title= for wikilink markup orig = torig; -- identify the failing |title= parameter elseif link:match ('^%a+:') then -- if the link is what looks like an interwiki local prefix = link:match ('^(%a+):'):lower(); -- get the interwiki prefix if cfg.inter_wiki_map[prefix] then -- if prefix is in the map, must have preceding colon orig = lorig; -- flag as error end end end if utilities.is_set (orig) then link = ''; -- unset utilities.set_message ('err_bad_paramlink', orig); -- URL or wikilink in |title= with |title-link=; end return link; -- link if ok, empty string else end --[[--------------------------< C H E C K _ U R L >------------------------------------------------------------ Determines whether a URL string appears to be valid. First we test for space characters. If any are found, return false. Then split the URL into scheme and domain portions, or for protocol-relative (//example.com) URLs, just the domain. Use is_url() to validate the two portions of the URL. If both are valid, or for protocol-relative if domain is valid, return true, else false. Because it is different from a standard URL, and because this module used external_link() to make external links that work for standard and news: links, we validate newsgroup names here. The specification for a newsgroup name is at https://tools.ietf.org/html/rfc5536#section-3.1.4 ]] local function check_url( url_str ) if nil == url_str:match ("^%S+$") then -- if there are any spaces in |url=value it can't be a proper URL return false; end local scheme, domain; scheme, domain = split_url (url_str); -- get scheme or nil and domain or nil from URL; if 'news:' == scheme then -- special case for newsgroups return domain:match('^[%a%d%+%-_]+%.[%a%d%+%-_%.]*[%a%d%+%-_]$'); end return is_url (scheme, domain); -- return true if value appears to be a valid URL end --[=[-------------------------< I S _ P A R A M E T E R _ E X T _ W I K I L I N K >---------------------------- Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first non-space characters following the opening bracket appear to be a URL. The test will also find external wikilinks that use protocol-relative URLs. Also finds bare URLs. The frontier pattern prevents a match on interwiki-links which are similar to scheme:path URLs. The tests that find bracketed URLs are required because the parameters that call this test (currently |title=, |chapter=, |work=, and |publisher=) may have wikilinks and there are articles or redirects like '//Hus' so, while uncommon, |title=[[//Hus]] is possible as might be [[en://Hus]]. ]=] local function is_parameter_ext_wikilink (value) local scheme, domain; if value:match ('%f[%[]%[%a%S*:%S+.*%]') then -- if ext. wikilink with scheme and domain: [xxxx://yyyyy.zzz] scheme, domain = split_url (value:match ('%f[%[]%[(%a%S*:%S+).*%]')); elseif value:match ('%f[%[]%[//%S+.*%]') then -- if protocol-relative ext. wikilink: [//yyyyy.zzz] scheme, domain = split_url (value:match ('%f[%[]%[(//%S+).*%]')); elseif value:match ('%a%S*:%S+') then -- if bare URL with scheme; may have leading or trailing plain text scheme, domain = split_url (value:match ('(%a%S*:%S+)')); elseif value:match ('//%S+') then -- if protocol-relative bare URL: //yyyyy.zzz; may have leading or trailing plain text scheme, domain = split_url (value:match ('(//%S+)')); -- what is left should be the domain else return false; -- didn't find anything that is obviously a URL end return is_url (scheme, domain); -- return true if value appears to be a valid URL end --[[-------------------------< C H E C K _ F O R _ U R L >----------------------------------------------------- loop through a list of parameters and their values. Look at the value and if it has an external link, emit an error message. ]] local function check_for_url (parameter_list, error_list) for k, v in pairs (parameter_list) do -- for each parameter in the list if is_parameter_ext_wikilink (v) then -- look at the value; if there is a URL add an error message table.insert (error_list, utilities.wrap_style ('parameter', k)); end end end --[[--------------------------< S A F E _ F O R _ U R L >------------------------------------------------------ Escape sequences for content that will be used for URL descriptions ]] local function safe_for_url( str ) if str:match( "%[%[.-%]%]" ) ~= nil then utilities.set_message ('err_wikilink_in_url', {}); end return str:gsub( '[%[%]\n]', { ['['] = '&#91;', [']'] = '&#93;', ['\n'] = ' ' } ); end --[[--------------------------< E X T E R N A L _ L I N K >---------------------------------------------------- Format an external link with error checking ]] local function external_link (URL, label, source, access) local err_msg = ''; local domain; local path; local base_url; if not utilities.is_set (label) then label = URL; if utilities.is_set (source) then utilities.set_message ('err_bare_url_missing_title', {utilities.wrap_style ('parameter', source)}); else error (cfg.messages["bare_url_no_origin"]); end end if not check_url (URL) then utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}); end domain, path = URL:match ('^([/%.%-%+:%a%d]+)([/%?#].*)$'); -- split the URL into scheme plus domain and path if path then -- if there is a path portion path = path:gsub ('[%[%]]', {['['] = '%5b', [']'] = '%5d'}); -- replace '[' and ']' with their percent-encoded values URL = table.concat ({domain, path}); -- and reassemble end base_url = table.concat ({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wiki-markup URL if utilities.is_set (access) then -- access level (subscription, registration, limited) base_url = utilities.substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon end return base_url; end --[[--------------------------< D E P R E C A T E D _ P A R A M E T E R >-------------------------------------- Categorize and emit an error message when the citation contains one or more deprecated parameters. The function includes the offending parameter name to the error message. Only one error message is emitted regardless of the number of deprecated parameters in the citation. added_deprecated_cat is a Boolean declared in page scope variables above ]] local function deprecated_parameter(name) if not added_deprecated_cat then added_deprecated_cat = true; -- note that we've added this category utilities.set_message ('err_deprecated_params', {name}); -- add error message end end --[=[-------------------------< K E R N _ Q U O T E S >-------------------------------------------------------- Apply kerning to open the space between the quote mark provided by the module and a leading or trailing quote mark contained in a |title= or |chapter= parameter's value. This function will positive kern either single or double quotes: "'Unkerned title with leading and trailing single quote marks'" " 'Kerned title with leading and trailing single quote marks' " (in real life the kerning isn't as wide as this example) Double single quotes (italic or bold wiki-markup) are not kerned. Replaces Unicode quote marks in plain text or in the label portion of a [[L|D]] style wikilink with typewriter quote marks regardless of the need for kerning. Unicode quote marks are not replaced in simple [[D]] wikilinks. Call this function for chapter titles, for website titles, etc.; not for book titles. ]=] local function kern_quotes (str) local cap = ''; local wl_type, label, link; wl_type, label, link = utilities.is_wikilink (str); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]] if 1 == wl_type then -- [[D]] simple wikilink with or without quote marks if mw.ustring.match (str, '%[%[[\"“”\'‘’].+[\"“”\'‘’]%]%]') then -- leading and trailing quote marks str = utilities.substitute (cfg.presentation['kern-left'], str); str = utilities.substitute (cfg.presentation['kern-right'], str); elseif mw.ustring.match (str, '%[%[[\"“”\'‘’].+%]%]') then -- leading quote marks str = utilities.substitute (cfg.presentation['kern-left'], str); elseif mw.ustring.match (str, '%[%[.+[\"“”\'‘’]%]%]') then -- trailing quote marks str = utilities.substitute (cfg.presentation['kern-right'], str); end else -- plain text or [[L|D]]; text in label variable label = mw.ustring.gsub (label, '[“”]', '\"'); -- replace “” (U+201C & U+201D) with " (typewriter double quote mark) label = mw.ustring.gsub (label, '[‘’]', '\''); -- replace ‘’ (U+2018 & U+2019) with ' (typewriter single quote mark) cap = mw.ustring.match (label, "^([\"\'][^\'].+)"); -- match leading double or single quote but not doubled single quotes (italic markup) if utilities.is_set (cap) then label = utilities.substitute (cfg.presentation['kern-left'], cap); end cap = mw.ustring.match (label, "^(.+[^\'][\"\'])$") -- match trailing double or single quote but not doubled single quotes (italic markup) if utilities.is_set (cap) then label = utilities.substitute (cfg.presentation['kern-right'], cap); end if 2 == wl_type then str = utilities.make_wikilink (link, label); -- reassemble the wikilink else str = label; end end return str; end --[[--------------------------< F O R M A T _ S C R I P T _ V A L U E >---------------------------------------- |script-title= holds title parameters that are not written in Latin-based scripts: Chinese, Japanese, Arabic, Hebrew, etc. These scripts should not be italicized and may be written right-to-left. The value supplied by |script-title= is concatenated onto Title after Title has been wrapped in italic markup. Regardless of language, all values provided by |script-title= are wrapped in <bdi>...</bdi> tags to isolate RTL languages from the English left to right. |script-title= provides a unique feature. The value in |script-title= may be prefixed with a two-character ISO 639-1 language code and a colon: |script-title=ja:*** *** (where * represents a Japanese character) Spaces between the two-character code and the colon and the colon and the first script character are allowed: |script-title=ja : *** *** |script-title=ja: *** *** |script-title=ja :*** *** Spaces preceding the prefix are allowed: |script-title = ja:*** *** The prefix is checked for validity. If it is a valid ISO 639-1 language code, the lang attribute (lang="ja") is added to the <bdi> tag so that browsers can know the language the tag contains. This may help the browser render the script more correctly. If the prefix is invalid, the lang attribute is not added. At this time there is no error message for this condition. Supports |script-title=, |script-chapter=, |script-<periodical>= ]] local function format_script_value (script_value, script_param) local lang=''; -- initialize to empty string local name; if script_value:match('^%l%l%l?%s*:') then -- if first 3 or 4 non-space characters are script language prefix lang = script_value:match('^(%l%l%l?)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script if not utilities.is_set (lang) then utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['missing title part']}); -- prefix without 'title'; add error message return ''; -- script_value was just the prefix so return empty string end -- if we get this far we have prefix and script name = cfg.lang_code_remap[lang] or mw.language.fetchLanguageName( lang, cfg.this_wiki_code ); -- get language name so that we can use it to categorize if utilities.is_set (name) then -- is prefix a proper ISO 639-1 language code? script_value = script_value:gsub ('^%l+%s*:%s*', ''); -- strip prefix from script -- is prefix one of these language codes? if utilities.in_array (lang, cfg.script_lang_codes) then utilities.add_prop_cat ('script', {name, lang}) else utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['unknown language code']}); -- unknown script-language; add error message end lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute else utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['invalid language code']}); -- invalid language code; add error message lang = ''; -- invalid so set lang to empty string end else utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['missing prefix']}); -- no language code prefix; add error message end script_value = utilities.substitute (cfg.presentation['bdi'], {lang, script_value}); -- isolate in case script is RTL return script_value; end --[[--------------------------< S C R I P T _ C O N C A T E N A T E >------------------------------------------ Initially for |title= and |script-title=, this function concatenates those two parameter values after the script value has been wrapped in <bdi> tags. ]] local function script_concatenate (title, script, script_param) if utilities.is_set (script) then script = format_script_value (script, script_param); -- <bdi> tags, lang attribute, categorization, etc.; returns empty string on error if utilities.is_set (script) then title = title .. ' ' .. script; -- concatenate title and script title end end return title; end --[[--------------------------< W R A P _ M S G >-------------------------------------------------------------- Applies additional message text to various parameter values. Supplied string is wrapped using a message_list configuration taking one argument. Supports lower case text for {{citation}} templates. Additional text taken from citation_config.messages - the reason this function is similar to but separate from wrap_style(). ]] local function wrap_msg (key, str, lower) if not utilities.is_set ( str ) then return ""; end if true == lower then local msg; msg = cfg.messages[key]:lower(); -- set the message to lower case before return utilities.substitute ( msg, str ); -- including template text else return utilities.substitute ( cfg.messages[key], str ); end end --[[----------------< W I K I S O U R C E _ U R L _ M A K E >------------------- Makes a Wikisource URL from Wikisource interwiki-link. Returns the URL and appropriate label; nil else. str is the value assigned to |chapter= (or aliases) or |title= or |title-link= ]] local function wikisource_url_make (str) local wl_type, D, L; local ws_url, ws_label; local wikisource_prefix = table.concat ({'https://', cfg.this_wiki_code, '.wikisource.org/wiki/'}); wl_type, D, L = utilities.is_wikilink (str); -- wl_type is 0 (not a wikilink), 1 (simple wikilink), 2 (complex wikilink) if 0 == wl_type then -- not a wikilink; might be from |title-link= str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace if utilities.is_set (str) then ws_url = table.concat ({ -- build a Wikisource URL wikisource_prefix, -- prefix str, -- article title }); ws_label = str; -- label for the URL end elseif 1 == wl_type then -- simple wikilink: [[Wikisource:ws article]] str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace if utilities.is_set (str) then ws_url = table.concat ({ -- build a Wikisource URL wikisource_prefix, -- prefix str, -- article title }); ws_label = str; -- label for the URL end elseif 2 == wl_type then -- non-so-simple wikilink: [[Wikisource:ws article|displayed text]] ([[L|D]]) str = L:match ('^[Ww]ikisource:(.+)') or L:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace if utilities.is_set (str) then ws_label = D; -- get ws article name from display portion of interwiki link ws_url = table.concat ({ -- build a Wikisource URL wikisource_prefix, -- prefix str, -- article title without namespace from link portion of wikilink }); end end if ws_url then ws_url = mw.uri.encode (ws_url, 'WIKI'); -- make a usable URL ws_url = ws_url:gsub ('%%23', '#'); -- undo percent-encoding of fragment marker end return ws_url, ws_label, L or D; -- return proper URL or nil and a label or nil end --[[----------------< F O R M A T _ P E R I O D I C A L >----------------------- Format the three periodical parameters: |script-<periodical>=, |<periodical>=, and |trans-<periodical>= into a single Periodical meta-parameter. ]] local function format_periodical (script_periodical, script_periodical_source, periodical, trans_periodical) if not utilities.is_set (periodical) then periodical = ''; -- to be safe for concatenation else periodical = utilities.wrap_style ('italic-title', periodical); -- style end periodical = script_concatenate (periodical, script_periodical, script_periodical_source); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped if utilities.is_set (trans_periodical) then trans_periodical = utilities.wrap_style ('trans-italic-title', trans_periodical); if utilities.is_set (periodical) then periodical = periodical .. ' ' .. trans_periodical; else -- here when trans-periodical without periodical or script-periodical periodical = trans_periodical; utilities.set_message ('err_trans_missing_title', {'periodical'}); end end return periodical; end --[[------------------< F O R M A T _ C H A P T E R _ T I T L E >--------------- Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=, and |chapter-url= into a single chapter meta- parameter (chapter_url_source used for error messages). ]] local function format_chapter_title (script_chapter, script_chapter_source, chapter, chapter_source, trans_chapter, trans_chapter_source, chapter_url, chapter_url_source, no_quotes, access) local ws_url, ws_label, L = wikisource_url_make (chapter); -- make a wikisource URL and label from a wikisource interwiki link if ws_url then ws_label = ws_label:gsub ('_', ' '); -- replace underscore separators with space characters chapter = ws_label; end if not utilities.is_set (chapter) then chapter = ''; -- to be safe for concatenation else if false == no_quotes then chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from module provided quote marks chapter = utilities.wrap_style ('quoted-title', chapter); end end chapter = script_concatenate (chapter, script_chapter, script_chapter_source); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped if utilities.is_set (chapter_url) then chapter = external_link (chapter_url, chapter, chapter_url_source, access); -- adds bare_url_missing_title error if appropriate elseif ws_url then chapter = external_link (ws_url, chapter .. '&nbsp;', 'ws link in chapter'); -- adds bare_url_missing_title error if appropriate; space char to move icon away from chap text; TODO: better way to do this? chapter = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, chapter}); end if utilities.is_set (trans_chapter) then trans_chapter = utilities.wrap_style ('trans-quoted-title', trans_chapter); if utilities.is_set (chapter) then chapter = chapter .. ' ' .. trans_chapter; else -- here when trans_chapter without chapter or script-chapter chapter = trans_chapter; chapter_source = trans_chapter_source:match ('trans%-?(.+)'); -- when no chapter, get matching name from trans-<param> utilities.set_message ('err_trans_missing_title', {chapter_source}); end end return chapter; end --[[----------------< H A S _ I N V I S I B L E _ C H A R S >------------------- This function searches a parameter's value for non-printable or invisible characters. The search stops at the first match. This function will detect the visible replacement character when it is part of the Wikisource. Detects but ignores nowiki and math stripmarkers. Also detects other named stripmarkers (gallery, math, pre, ref) and identifies them with a slightly different error message. See also coins_cleanup(). Output of this function is an error message that identifies the character or the Unicode group, or the stripmarker that was detected along with its position (or, for multi-byte characters, the position of its first byte) in the parameter value. ]] local function has_invisible_chars (param, v) local position = ''; -- position of invisible char or starting position of stripmarker local capture; -- used by stripmarker detection to hold name of the stripmarker local stripmarker; -- boolean set true when a stripmarker is found capture = string.match (v, '[%w%p ]*'); -- test for values that are simple ASCII text and bypass other tests if true if capture == v then -- if same there are no Unicode characters return; end for _, invisible_char in ipairs (cfg.invisible_chars) do local char_name = invisible_char[1]; -- the character or group name local pattern = invisible_char[2]; -- the pattern used to find it position, _, capture = mw.ustring.find (v, pattern); -- see if the parameter value contains characters that match the pattern if position and (cfg.invisible_defs.zwj == capture) then -- if we found a zero-width joiner character if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts position = nil; -- unset position elseif cfg.emoji[mw.ustring.codepoint (v, position+1)] then -- is zwj followed by a character listed in emoji{}? position = nil; -- unset position end end if position then if 'nowiki' == capture or 'math' == capture or -- nowiki and math stripmarkers (not an error condition) ('templatestyles' == capture and utilities.in_array (param, {'id', 'quote'})) then -- templatestyles stripmarker allowed in these parameters stripmarker = true; -- set a flag elseif true == stripmarker and cfg.invisible_defs.del == capture then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker position = nil; -- unset else local err_msg; if capture and not (cfg.invisible_defs.del == capture or cfg.invisible_defs.zwj == capture) then err_msg = capture .. ' ' .. char_name; else err_msg = char_name .. ' ' .. 'character'; end utilities.set_message ('err_invisible_char', {err_msg, utilities.wrap_style ('parameter', param), position}); -- add error message return; -- and done with this parameter end end end end --[[-------------------< A R G U M E N T _ W R A P P E R >---------------------- Argument wrapper. This function provides support for argument mapping defined in the configuration file so that multiple names can be transparently aliased to single internal variable. ]] local function argument_wrapper ( args ) local origin = {}; return setmetatable({ ORIGIN = function ( self, k ) local dummy = self[k]; -- force the variable to be loaded. return origin[k]; end }, { __index = function ( tbl, k ) if origin[k] ~= nil then return nil; end local args, list, v = args, cfg.aliases[k]; if type( list ) == 'table' then v, origin[k] = utilities.select_one ( args, list, 'err_redundant_parameters' ); if origin[k] == nil then origin[k] = ''; -- Empty string, not nil end elseif list ~= nil then v, origin[k] = args[list], list; else -- maybe let through instead of raising an error? -- v, origin[k] = args[k], k; error( cfg.messages['unknown_argument_map'] .. ': ' .. k); end -- Empty strings, not nil; if v == nil then v = ''; origin[k] = ''; end tbl = rawset( tbl, k, v ); return v; end, }); end --[[--------------------------< N O W R A P _ D A T E >------------------------- When date is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>. When date is DD MMMM YYYY or is MMMM DD, YYYY then wrap in nowrap span: <span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY DOES NOT yet support MMMM YYYY or any of the date ranges. ]] local function nowrap_date (date) local cap = ''; local cap2 = ''; if date:match("^%d%d%d%d%-%d%d%-%d%d$") then date = utilities.substitute (cfg.presentation['nowrap1'], date); elseif date:match("^%a+%s*%d%d?,%s+%d%d%d%d$") or date:match ("^%d%d?%s*%a+%s+%d%d%d%d$") then cap, cap2 = string.match (date, "^(.*)%s+(%d%d%d%d)$"); date = utilities.substitute (cfg.presentation['nowrap2'], {cap, cap2}); end return date; end --[[--------------------------< S E T _ T I T L E T Y P E >--------------------- This function sets default title types (equivalent to the citation including |type=<default value>) for those templates that have defaults. Also handles the special case where it is desirable to omit the title type from the rendered citation (|type=none). ]] local function set_titletype (cite_class, title_type) if utilities.is_set (title_type) then if 'none' == cfg.keywords_xlate[title_type] then title_type = ''; -- if |type=none then type parameter not displayed end return title_type; -- if |type= has been set to any other value use that value end return cfg.title_types [cite_class] or ''; -- set template's default title type; else empty string for concatenation end --[[--------------------------< S A F E _ J O I N >----------------------------- Joins a sequence of strings together while checking for duplicate separation characters. ]] local function safe_join( tbl, duplicate_char ) local f = {}; -- create a function table appropriate to type of 'duplicate character' if 1 == #duplicate_char then -- for single byte ASCII characters use the string library functions f.gsub = string.gsub f.match = string.match f.sub = string.sub else -- for multi-byte characters use the ustring library functions f.gsub = mw.ustring.gsub f.match = mw.ustring.match f.sub = mw.ustring.sub end local str = ''; -- the output string local comp = ''; -- what does 'comp' mean? local end_chr = ''; local trim; for _, value in ipairs( tbl ) do if value == nil then value = ''; end if str == '' then -- if output string is empty str = value; -- assign value to it (first time through the loop) elseif value ~= '' then if value:sub(1, 1) == '<' then -- special case of values enclosed in spans and other markup. comp = value:gsub( "%b<>", "" ); -- remove HTML markup (<span>string</span> -> string) else comp = value; end -- typically duplicate_char is sepc if f.sub(comp, 1, 1) == duplicate_char then -- is first character same as duplicate_char? why test first character? -- Because individual string segments often (always?) begin with terminal punct for the -- preceding segment: 'First element' .. 'sepc next element' .. etc.? trim = false; end_chr = f.sub(str, -1, -1); -- get the last character of the output string -- str = str .. "<HERE(enchr=" .. end_chr .. ")" -- debug stuff? if end_chr == duplicate_char then -- if same as separator str = f.sub(str, 1, -2); -- remove it elseif end_chr == "'" then -- if it might be wiki-markup if f.sub(str, -3, -1) == duplicate_char .. "''" then -- if last three chars of str are sepc'' str = f.sub(str, 1, -4) .. "''"; -- remove them and add back '' elseif f.sub(str, -5, -1) == duplicate_char .. "]]''" then -- if last five chars of str are sepc]]'' trim = true; -- why? why do this and next differently from previous? elseif f.sub(str, -4, -1) == duplicate_char .. "]''" then -- if last four chars of str are sepc]'' trim = true; -- same question end elseif end_chr == "]" then -- if it might be wiki-markup if f.sub(str, -3, -1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink trim = true; elseif f.sub(str, -3, -1) == duplicate_char .. '"]' then -- if last three chars of str are sepc"] quoted external link trim = true; elseif f.sub(str, -2, -1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link trim = true; elseif f.sub(str, -4, -1) == duplicate_char .. "'']" then -- normal case when |url=something & |title=Title. trim = true; end elseif end_chr == " " then -- if last char of output string is a space if f.sub(str, -2, -1) == duplicate_char .. " " then -- if last two chars of str are <sepc><space> str = f.sub(str, 1, -3); -- remove them both end end if trim then if value ~= comp then -- value does not equal comp when value contains HTML markup local dup2 = duplicate_char; if f.match(dup2, "%A" ) then dup2 = "%" .. dup2; end -- if duplicate_char not a letter then escape it value = f.gsub(value, "(%b<>)" .. dup2, "%1", 1 ) -- remove duplicate_char if it follows HTML markup else value = f.sub(value, 2, -1 ); -- remove duplicate_char when it is first character end end end str = str .. value; -- add it to the output string end end return str; end --[[--------------------------< I S _ S U F F I X >----------------------------- returns true if suffix is properly formed Jr, Sr, or ordinal in the range 1–9. Puncutation not allowed. ]] local function is_suffix (suffix) if utilities.in_array (suffix, {'Jr', 'Sr', 'Jnr', 'Snr', '1st', '2nd', '3rd'}) or suffix:match ('^%dth$') then return true; end return false; end --[[--------------------< I S _ G O O D _ V A N C _ N A M E >------------------- For Vancouver style, author/editor names are supposed to be rendered in Latin (read ASCII) characters. When a name uses characters that contain diacritical marks, those characters are to be converted to the corresponding Latin character. When a name is written using a non-Latin alphabet or logogram, that name is to be transliterated into Latin characters. The module doesn't do this so editors may/must. This test allows |first= and |last= names to contain any of the letters defined in the four Unicode Latin character sets [http://www.unicode.org/charts/PDF/U0000.pdf C0 Controls and Basic Latin] 0041–005A, 0061–007A [http://www.unicode.org/charts/PDF/U0080.pdf C1 Controls and Latin-1 Supplement] 00C0–00D6, 00D8–00F6, 00F8–00FF [http://www.unicode.org/charts/PDF/U0100.pdf Latin Extended-A] 0100–017F [http://www.unicode.org/charts/PDF/U0180.pdf Latin Extended-B] 0180–01BF, 01C4–024F |lastn= also allowed to contain hyphens, spaces, and apostrophes. (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/) |firstn= also allowed to contain hyphens, spaces, apostrophes, and periods This original test: if nil == mw.ustring.find (last, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%']*$") or nil == mw.ustring.find (first, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%'%.]+[2-6%a]*$") then was written outside of the code editor and pasted here because the code editor gets confused between character insertion point and cursor position. The test has been rewritten to use decimal character escape sequence for the individual bytes of the Unicode characters so that it is not necessary to use an external editor to maintain this code. \195\128-\195\150 – À-Ö (U+00C0–U+00D6 – C0 controls) \195\152-\195\182 – Ø-ö (U+00D8-U+00F6 – C0 controls) \195\184-\198\191 – ø-ƿ (U+00F8-U+01BF – C0 controls, Latin extended A & B) \199\132-\201\143 – DŽ-ɏ (U+01C4-U+024F – Latin extended B) ]] local function is_good_vanc_name (last, first, suffix, position) if not suffix then if first:find ('[,%s]') then -- when there is a space or comma, might be first name/initials + generational suffix first = first:match ('(.-)[,%s]+'); -- get name/initials suffix = first:match ('[,%s]+(.+)$'); -- get generational suffix end end if utilities.is_set (suffix) then if not is_suffix (suffix) then add_vanc_error (cfg.err_msg_supl.suffix, position); return false; -- not a name with an appropriate suffix end end if nil == mw.ustring.find (last, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%']*$") or nil == mw.ustring.find (first, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%'%.]*$") then add_vanc_error (cfg.err_msg_supl['non-Latin char'], position); return false; -- not a string of Latin characters; Vancouver requires Romanization end; return true; end --[[--------------------------< R E D U C E _ T O _ I N I T I A L S >------------------------------------------ Attempts to convert names to initials in support of |name-list-style=vanc. Names in |firstn= may be separated by spaces or hyphens, or for initials, a period. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35062/. Vancouver style requires family rank designations (Jr, II, III, etc.) to be rendered as Jr, 2nd, 3rd, etc. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35085/. This code only accepts and understands generational suffix in the Vancouver format because Roman numerals look like, and can be mistaken for, initials. This function uses ustring functions because firstname initials may be any of the Unicode Latin characters accepted by is_good_vanc_name (). ]] local function reduce_to_initials(first, position) local name, suffix = mw.ustring.match(first, "^(%u+) ([%dJS][%drndth]+)$"); if not name then -- if not initials and a suffix name = mw.ustring.match(first, "^(%u+)$"); -- is it just initials? end if name then -- if first is initials with or without suffix if 3 > mw.ustring.len (name) then -- if one or two initials if suffix then -- if there is a suffix if is_suffix (suffix) then -- is it legitimate? return first; -- one or two initials and a valid suffix so nothing to do else add_vanc_error (cfg.err_msg_supl.suffix, position); -- one or two initials with invalid suffix so error message return first; -- and return first unmolested end else return first; -- one or two initials without suffix; nothing to do end end end -- if here then name has 3 or more uppercase letters so treat them as a word local initials, names = {}, {}; -- tables to hold name parts and initials local i = 1; -- counter for number of initials names = mw.text.split (first, '[%s,]+'); -- split into a table of names and possible suffix while names[i] do -- loop through the table if 1 < i and names[i]:match ('[%dJS][%drndth]+%.?$') then -- if not the first name, and looks like a suffix (may have trailing dot) names[i] = names[i]:gsub ('%.', ''); -- remove terminal dot if present if is_suffix (names[i]) then -- if a legitimate suffix table.insert (initials, ' ' .. names[i]); -- add a separator space, insert at end of initials table break; -- and done because suffix must fall at the end of a name end -- no error message if not a suffix; possibly because of Romanization end if 3 > i then table.insert (initials, mw.ustring.sub(names[i], 1, 1)); -- insert the initial at end of initials table end i = i + 1; -- bump the counter end return table.concat(initials) -- Vancouver format does not include spaces. end --[[--------------------------< L I S T _ P E O P L E >-------------------------- Formats a list of people (authors, contributors, editors, interviewers, translators) names in the list will be linked when |<name>-link= has a value |<name>-mask- does NOT have a value; masked names are presumed to have been rendered previously so should have been linked there when |<name>-mask=0, the associated name is not rendered ]] local function list_people (control, people, etal) local sep; local namesep; local format = control.format; local maximum = control.maximum; local name_list = {}; if 'vanc' == format then -- Vancouver-like name styling? sep = cfg.presentation['sep_nl_vanc']; -- name-list separator between names is a comma namesep = cfg.presentation['sep_name_vanc']; -- last/first separator is a space else sep = cfg.presentation['sep_nl']; -- name-list separator between names is a semicolon namesep = cfg.presentation['sep_name']; -- last/first separator is <comma><space> end if sep:sub (-1, -1) ~= " " then sep = sep .. " " end if utilities.is_set (maximum) and maximum < 1 then return "", 0; end -- returned 0 is for EditorCount; not used for other names for i, person in ipairs (people) do if utilities.is_set (person.last) then local mask = person.mask; local one; local sep_one = sep; if utilities.is_set (maximum) and i > maximum then etal = true; break; end if mask then local n = tonumber (mask); -- convert to a number if it can be converted; nil else if n then one = 0 ~= n and string.rep("&mdash;", n) or nil; -- make a string of (n > 0) mdashes, nil else, to replace name person.link = nil; -- don't create link to name if name is replaces with mdash string or has been set nil else one = mask; -- replace name with mask text (must include name-list separator) sep_one = " "; -- modify name-list separator end else one = person.last; -- get surname local first = person.first -- get given name if utilities.is_set (first) then if ("vanc" == format) then -- if Vancouver format one = one:gsub ('%.', ''); -- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/) if not person.corporate and is_good_vanc_name (one, first, nil, i) then -- and name is all Latin characters; corporate authors not tested first = reduce_to_initials (first, i); -- attempt to convert first name(s) to initials end end one = one .. namesep .. first; end end if utilities.is_set (person.link) then one = utilities.make_wikilink (person.link, one); -- link author/editor end if one then -- if <one> has a value (name, mdash replacement, or mask text replacement) table.insert (name_list, one); -- add it to the list of names table.insert (name_list, sep_one); -- add the proper name-list separator end end end local count = #name_list / 2; -- (number of names + number of separators) divided by 2 if 0 < count then if 1 < count and not etal then if 'amp' == format then name_list[#name_list-2] = " & "; -- replace last separator with ampersand text elseif 'and' == format then if 2 == count then name_list[#name_list-2] = cfg.presentation.sep_nl_and; -- replace last separator with 'and' text else name_list[#name_list-2] = cfg.presentation.sep_nl_end; -- replace last separator with '(sep) and' text end end end name_list[#name_list] = nil; -- erase the last separator end local result = table.concat (name_list); -- construct list if etal and utilities.is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list result = result .. sep .. ' ' .. cfg.messages['et al']; -- we've got a last-first list and etal so add et al. end return result, count; -- return name-list string and count of number of names (count used for editor names only) end --[[--------------------< M A K E _ C I T E R E F _ I D >----------------------- Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise returns an empty string. namelist is one of the contributor-, author-, or editor-name lists chosen in that order. year is Year or anchor_year. ]] local function make_citeref_id (namelist, year) local names={}; -- a table for the one to four names and year for i,v in ipairs (namelist) do -- loop through the list and take up to the first four last names names[i] = v.last if i == 4 then break end -- if four then done end table.insert (names, year); -- add the year at the end local id = table.concat(names); -- concatenate names and year for CITEREF id if utilities.is_set (id) then -- if concatenation is not an empty string return "CITEREF" .. id; -- add the CITEREF portion else return ''; -- return an empty string; no reason to include CITEREF id in this citation end end --[[--------------------------< C I T E _ C L A S S _A T T R I B U T E _M A K E >------------------------------ construct <cite> tag class attribute for this citation. <cite_class> – config.CitationClass from calling template <mode> – value from |mode= parameter ]] local function cite_class_attribute_make (cite_class, mode) local class_t = {}; table.insert (class_t, 'citation'); -- required for blue highlight if 'citation' ~= cite_class then table.insert (class_t, cite_class); -- identify this template for user css table.insert (class_t, utilities.is_set (mode) and mode or 'cs1'); -- identify the citation style for user css or javascript else table.insert (class_t, utilities.is_set (mode) and mode or 'cs2'); -- identify the citation style for user css or javascript end for _, prop_key in ipairs (z.prop_keys_t) do table.insert (class_t, prop_key); -- identify various properties for user css or javascript end return table.concat (class_t, ' '); -- make a big string and done end --[[---------------------< N A M E _ H A S _ E T A L >-------------------------- Evaluates the content of name parameters (author, editor, etc.) for variations on the theme of et al. If found, the et al. is removed, a flag is set to true and the function returns the modified name and the flag. This function never sets the flag to false but returns its previous state because it may have been set by previous passes through this function or by the associated |display-<names>=etal parameter ]] local function name_has_etal (name, etal, nocat, param) if utilities.is_set (name) then -- name can be nil in which case just return local patterns = cfg.et_al_patterns; -- get patterns from configuration for _, pattern in ipairs (patterns) do -- loop through all of the patterns if name:match (pattern) then -- if this 'et al' pattern is found in name name = name:gsub (pattern, ''); -- remove the offending text etal = true; -- set flag (may have been set previously here or by |display-<names>=etal) if not nocat then -- no categorization for |vauthors= utilities.set_message ('err_etal', {param}); -- and set an error if not added end end end end return name, etal; end --[[---------------------< N A M E _ I S _ N U M E R I C >---------------------- Add maint cat when name parameter value does not contain letters. Does not catch mixed alphanumeric names so |last=A. Green (1922-1987) does not get caught in the current version of this test but |first=(1888) is caught. returns nothing ]] local function name_is_numeric (name, list_name) if utilities.is_set (name) then if mw.ustring.match (name, '^[%A]+$') then -- when name does not contain any letters utilities.set_message ('maint_numeric_names', cfg.special_case_translation [list_name]); -- add a maint cat for this template end end end --[[-----------------< N A M E _ H A S _ M U L T _ N A M E S >------------------ Evaluates the content of last/surname (authors etc.) parameters for multiple names. Multiple names are indicated if there is more than one comma or any "unescaped" semicolons. Escaped semicolons are ones used as part of selected HTML entities. If the condition is met, the function adds the multiple name maintenance category. returns nothing ]] local function name_has_mult_names (name, list_name) local _, commas, semicolons, nbsps; if utilities.is_set (name) then _, commas = name:gsub (',', ''); -- count the number of commas _, semicolons = name:gsub (';', ''); -- count the number of semicolons -- nbsps probably should be its own separate count rather than merged in -- some way with semicolons because Lua patterns do not support the -- grouping operator that regex does, which means there is no way to add -- more entities to escape except by adding more counts with the new -- entities _, nbsps = name:gsub ('&nbsp;',''); -- count nbsps -- There is exactly 1 semicolon per &nbsp; entity, so subtract nbsps -- from semicolons to 'escape' them. If additional entities are added, -- they also can be subtracted. if 1 < commas or 0 < (semicolons - nbsps) then utilities.set_message ('maint_mult_names', cfg.special_case_translation [list_name]); -- add a maint message end end end --[=[-------------------------< I S _ G E N E R I C >---------------------------------------------------------- Compares values assigned to various parameters according to the string provided as <item> in the function call. <item> can have on of two values: 'generic_names' – for name-holding parameters: |last=, |first=, |editor-last=, etc 'generic_titles' – for |title= There are two types of generic tests. The 'accept' tests look for a pattern that should not be rejected by the 'reject' test. For example, |author=[[John Smith (author)|Smith, John]] would be rejected by the 'author' reject test. But piped wikilinks with 'author' disambiguation should not be rejected so the 'accept' test prevents that from happening. Accept tests are always performed before reject tests. Each of the 'accept' and 'reject' sequence tables hold tables for en.wiki (['en']) and local.wiki (['local']) that each can hold a test sequence table The sequence table holds, at index [1], a test pattern, and, at index [2], a boolean control value. The control value tells string.find() or mw.ustring.find() to do plain-text search (true) or a pattern search (false). The intent of all this complexity is to make these searches as fast as possible so that we don't run out of processing time on very large articles. Returns true when a reject test finds the pattern or string false when an accept test finds the pattern or string nil else ]=] local function is_generic (item, value, wiki) local test_val; local str_lower = { -- use string.lower() for en.wiki (['en']) and use mw.ustring.lower() or local.wiki (['local']) ['en'] = string.lower, ['local'] = mw.ustring.lower, } local str_find = { -- use string.find() for en.wiki (['en']) and use mw.ustring.find() or local.wiki (['local']) ['en'] = string.find, ['local'] = mw.ustring.find, } local function test (val, test_t, wiki) -- local function to do the testing; <wiki> selects lower() and find() functions val = test_t[2] and str_lower[wiki](value) or val; -- when <test_t[2]> set to 'true', plaintext search using lowercase value return str_find[wiki] (val, test_t[1], 1, test_t[2]); -- return nil when not found or matched end local test_types_t = {'accept', 'reject'}; -- test accept patterns first, then reject patterns local wikis_t = {'en', 'local'}; -- do tests for each of these keys; en.wiki first, local.wiki second for _, test_type in ipairs (test_types_t) do -- for each test type for _, generic_value in pairs (cfg.special_case_translation[item][test_type]) do -- spin through the list of generic value fragments to accept or reject for _, wiki in ipairs (wikis_t) do if generic_value[wiki] then if test (value, generic_value[wiki], wiki) then -- go do the test return ('reject' == test_type); -- param value rejected, return true; false else end end end end end end --[[--------------------------< N A M E _ I S _ G E N E R I C >------------------------------------------------ calls is_generic() to determine if <name> is a 'generic name' listed in cfg.generic_names; <name_alias> is the parameter name used in error messaging ]] local function name_is_generic (name, name_alias) if not added_generic_name_errs and is_generic ('generic_names', name) then utilities.set_message ('err_generic_name', name_alias); -- set an error message added_generic_name_errs = true; end end --[[--------------------------< N A M E _ C H E C K S >-------------------------------------------------------- This function calls various name checking functions used to validate the content of the various name-holding parameters. ]] local function name_checks (last, first, list_name, last_alias, first_alias) local accept_name; if utilities.is_set (last) then last, accept_name = utilities.has_accept_as_written (last); -- remove accept-this-as-written markup when it wraps all of <last> if not accept_name then -- <last> not wrapped in accept-as-written markup name_has_mult_names (last, list_name); -- check for multiple names in the parameter (last only) name_is_numeric (last, list_name); -- check for names that are composed of digits and punctuation name_is_generic (last, last_alias); -- check for names found in the generic names list end end if utilities.is_set (first) then first, accept_name = utilities.has_accept_as_written (first); -- remove accept-this-as-written markup when it wraps all of <first> if not accept_name then -- <first> not wrapped in accept-as-written markup name_is_numeric (first, list_name); -- check for names that are composed of digits and punctuation name_is_generic (first, first_alias); -- check for names found in the generic names list end local wl_type, D = utilities.is_wikilink (first); if 0 ~= wl_type then first = D; utilities.set_message ('err_bad_paramlink', first_alias); end end return last, first; -- done end --[[----------------------< E X T R A C T _ N A M E S >------------------------- Gets name list from the input arguments Searches through args in sequential order to find |lastn= and |firstn= parameters (or their aliases), and their matching link and mask parameters. Stops searching when both |lastn= and |firstn= are not found in args after two sequential attempts: found |last1=, |last2=, and |last3= but doesn't find |last4= and |last5= then the search is done. This function emits an error message when there is a |firstn= without a matching |lastn=. When there are 'holes' in the list of last names, |last1= and |last3= are present but |last2= is missing, an error message is emitted. |lastn= is not required to have a matching |firstn=. When an author or editor parameter contains some form of 'et al.', the 'et al.' is stripped from the parameter and a flag (etal) returned that will cause list_people() to add the static 'et al.' text from Module:Citation/CS1/Configuration. This keeps 'et al.' out of the template's metadata. When this occurs, an error is emitted. ]] local function extract_names(args, list_name) local names = {}; -- table of names local last; -- individual name components local first; local link; local mask; local i = 1; -- loop counter/indexer local n = 1; -- output table indexer local count = 0; -- used to count the number of times we haven't found a |last= (or alias for authors, |editor-last or alias for editors) local etal = false; -- return value set to true when we find some form of et al. in an author parameter local last_alias, first_alias, link_alias; -- selected parameter aliases used in error messaging while true do last, last_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'err_redundant_parameters', i ); -- search through args for name components beginning at 1 first, first_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'err_redundant_parameters', i ); link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ); mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i ); last, etal = name_has_etal (last, etal, false, last_alias); -- find and remove variations on et al. first, etal = name_has_etal (first, etal, false, first_alias); -- find and remove variations on et al. last, first = name_checks (last, first, list_name, last_alias, first_alias); -- multiple names, extraneous annotation, etc. checks if first and not last then -- if there is a firstn without a matching lastn local alias = first_alias:find ('given', 1, true) and 'given' or 'first'; -- get first or given form of the alias utilities.set_message ('err_first_missing_last', { first_alias, -- param name of alias missing its mate first_alias:gsub (alias, {['first'] = 'last', ['given'] = 'surname'}), -- make param name appropriate to the alias form }); -- add this error message elseif not first and not last then -- if both firstn and lastn aren't found, are we done? count = count + 1; -- number of times we haven't found last and first if 2 <= count then -- two missing names and we give up break; -- normal exit or there is a two-name hole in the list; can't tell which end else -- we have last with or without a first local result; link = link_title_ok (link, link_alias, last, last_alias); -- check for improper wiki-markup if first then link = link_title_ok (link, link_alias, first, first_alias); -- check for improper wiki-markup end names[n] = {last = last, first = first, link = link, mask = mask, corporate = false}; -- add this name to our names list (corporate for |vauthors= only) n = n + 1; -- point to next location in the names table if 1 == count then -- if the previous name was missing utilities.set_message ('err_missing_name', {list_name:match ("(%w+)List"):lower(), i - 1}); -- add this error message end count = 0; -- reset the counter, we're looking for two consecutive missing names end i = i + 1; -- point to next args location end return names, etal; -- all done, return our list of names and the etal flag end --[[--------------------------< N A M E _ T A G _ G E T >------------------------------------------------------ attempt to decode |language=<lang_param> and return language name and matching tag; nil else. This function looks for: <lang_param> as a tag in cfg.lang_code_remap{} <lang_param> as a name in cfg.lang_name_remap{} <lang_param> as a name in cfg.mw_languages_by_name_t <lang_param> as a tag in cfg.mw_languages_by_tag_t when those fail, presume that <lang_param> is an IETF-like tag that MediaWiki does not recognize. Strip all script, region, variant, whatever subtags from <lang_param> to leave just a two or three character language tag and look for the new <lang_param> in cfg.mw_languages_by_tag_t{} on success, returns name (in properly capitalized form) and matching tag (in lowercase); on failure returns nil ]] local function name_tag_get (lang_param) local lang_param_lc = mw.ustring.lower (lang_param); -- use lowercase as an index into the various tables local name; local tag; name = cfg.lang_code_remap[lang_param_lc]; -- assume <lang_param_lc> is a tag; attempt to get remapped language name if name then -- when <name>, <lang_param> is a tag for a remapped language name return name, lang_param_lc; -- so return <name> from remap and <lang_param_lc> end tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- still assuming that <lang_param_lc> is a tag; strip script, region, variant subtags name = cfg.lang_code_remap[tag]; -- attempt to get remapped language name with language subtag only if name then -- when <name>, <tag> is a tag for a remapped language name return name, tag; -- so return <name> from remap and <tag> end if cfg.lang_name_remap[lang_param_lc] then -- not a tag, assume <lang_param_lc> is a name; attempt to get remapped language tag return cfg.lang_name_remap[lang_param_lc][1], cfg.lang_name_remap[lang_param_lc][2]; -- for this <lang_param_lc>, return a (possibly) new name and appropriate tag end tag = cfg.mw_languages_by_name_t[lang_param_lc]; -- assume that <lang_param_lc> is a language name; attempt to get its matching tag if tag then return cfg.mw_languages_by_tag_t[tag], tag; -- <lang_param_lc> is a name so return the name from the table and <tag> end name = cfg.mw_languages_by_tag_t[lang_param_lc]; -- assume that <lang_param_lc> is a tag; attempt to get its matching language name if name then return name, lang_param_lc; -- <lang_param_lc> is a tag so return it and <name> end tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- is <lang_param_lc> an IETF-like tag that MediaWiki doesn't recognize? <tag> gets the language subtag; nil else if tag then name = cfg.mw_languages_by_tag_t[tag]; -- attempt to get a language name using the shortened <tag> if name then return name, tag; -- <lang_param_lc> is an unrecognized IETF-like tag so return <name> and language subtag end end end --[[-------------------< L A N G U A G E _ P A R A M E T E R >------------------ Gets language name from a provided two- or three-character ISO 639 code. If a code is recognized by MediaWiki, use the returned name; if not, then use the value that was provided with the language parameter. When |language= contains a recognized language (either code or name), the page is assigned to the category for that code: Category:Norwegian-language sources (no). For valid three-character code languages, the page is assigned to the single category for '639-2' codes: Category:CS1 ISO 639-2 language sources. Languages that are the same as the local wiki are not categorized. MediaWiki does not recognize three-character equivalents of two-character codes: code 'ar' is recognized but code 'ara' is not. This function supports multiple languages in the form |language=nb, French, th where the language names or codes are separated from each other by commas with optional space characters. ]] local function language_parameter (lang) local tag; -- some form of IETF-like language tag; language subtag with optional region, sript, vatiant, etc subtags local lang_subtag; -- ve populates |language= with mostly unecessary region subtags the MediaWiki does not recognize; this is the base language subtag local name; -- the language name local language_list = {}; -- table of language names to be rendered local names_t = {}; -- table made from the value assigned to |language= local this_wiki_name = mw.language.fetchLanguageName (cfg.this_wiki_code, cfg.this_wiki_code); -- get this wiki's language name names_t = mw.text.split (lang, '%s*,%s*'); -- names should be a comma separated list for _, lang in ipairs (names_t) do -- reuse lang here because we don't yet know if lang is a language name or a language tag name, tag = name_tag_get (lang); -- attempt to get name/tag pair for <lang>; <name> has proper capitalization; <tag> is lowercase if utilities.is_set (tag) then lang_subtag = tag:gsub ('^(%a%a%a?)%-.*', '%1'); -- for categorization, strip any IETF-like tags from language tag if cfg.this_wiki_code ~= lang_subtag then -- when the language is not the same as this wiki's language if 2 == lang_subtag:len() then -- and is a two-character tag -- utilities.add_prop_cat ('foreign-lang-source', {name, lang_subtag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization utilities.add_prop_cat ('foreign-lang-source', {name, tag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization else -- or is a recognized language (but has a three-character tag) utilities.add_prop_cat ('foreign-lang-source-2', {lang_subtag}, lang_subtag); -- categorize it differently TODO: support multiple three-character tag categories per cs1|2 template? end elseif cfg.local_lang_cat_enable then -- when the language and this wiki's language are the same and categorization is enabled utilities.add_prop_cat ('local-lang-source', {name, lang_subtag}); -- categorize it end else name = lang; -- return whatever <lang> has so that we show something utilities.set_message ('maint_unknown_lang'); -- add maint category if not already added end table.insert (language_list, name); name = ''; -- so we can reuse it end name = utilities.make_sep_list (#language_list, language_list); if (1 == #language_list) and (lang_subtag == cfg.this_wiki_code) then -- when only one language, find lang name in this wiki lang name; for |language=en-us, 'English' in 'American English' return ''; -- if one language and that language is this wiki's return an empty string (no annotation) end return (" " .. wrap_msg ('language', name)); -- otherwise wrap with '(in ...)' --[[ TODO: should only return blank or name rather than full list so we can clean up the bunched parenthetical elements Language, Type, Format ]] end --[[-----------------------< S E T _ C S _ S T Y L E >-------------------------- Gets the default CS style configuration for the given mode. Returns default separator and either postscript as passed in or the default. In CS1, the default postscript and separator are '.'. In CS2, the default postscript is the empty string and the default separator is ','. ]] local function set_cs_style (postscript, mode) if utilities.is_set(postscript) then -- emit a maintenance message if user postscript is the default cs1 postscript -- we catch the opposite case for cs2 in set_style if mode == 'cs1' and postscript == cfg.presentation['ps_' .. mode] then utilities.set_message ('maint_postscript'); end else postscript = cfg.presentation['ps_' .. mode]; end return cfg.presentation['sep_' .. mode], postscript; end --[[--------------------------< S E T _ S T Y L E >----------------------------- Sets the separator and postscript styles. Checks the |mode= first and the #invoke CitationClass second. Removes the postscript if postscript == none. ]] local function set_style (mode, postscript, cite_class) local sep; if 'cs2' == mode then sep, postscript = set_cs_style (postscript, 'cs2'); elseif 'cs1' == mode then sep, postscript = set_cs_style (postscript, 'cs1'); elseif 'citation' == cite_class then sep, postscript = set_cs_style (postscript, 'cs2'); else sep, postscript = set_cs_style (postscript, 'cs1'); end if cfg.keywords_xlate[postscript:lower()] == 'none' then -- emit a maintenance message if user postscript is the default cs2 postscript -- we catch the opposite case for cs1 in set_cs_style if 'cs2' == mode or 'citation' == cite_class then utilities.set_message ('maint_postscript'); end postscript = ''; end return sep, postscript end --[=[-------------------------< I S _ P D F >----------------------------------- Determines if a URL has the file extension that is one of the PDF file extensions used by [[MediaWiki:Common.css]] when applying the PDF icon to external links. returns true if file extension is one of the recognized extensions, else false ]=] local function is_pdf (url) return url:match ('%.pdf$') or url:match ('%.PDF$') or url:match ('%.pdf[%?#]') or url:match ('%.PDF[%?#]') or url:match ('%.PDF&#035') or url:match ('%.pdf&#035'); end --[[--------------------------< S T Y L E _ F O R M A T >----------------------- Applies CSS style to |format=, |chapter-format=, etc. Also emits an error message if the format parameter does not have a matching URL parameter. If the format parameter is not set and the URL contains a file extension that is recognized as a PDF document by MediaWiki's commons.css, this code will set the format parameter to (PDF) with the appropriate styling. ]] local function style_format (format, url, fmt_param, url_param) if utilities.is_set (format) then format = utilities.wrap_style ('format', format); -- add leading space, parentheses, resize if not utilities.is_set (url) then utilities.set_message ('err_format_missing_url', {fmt_param, url_param}); -- add an error message end elseif is_pdf (url) then -- format is not set so if URL is a PDF file then format = utilities.wrap_style ('format', 'PDF'); -- set format to PDF else format = ''; -- empty string for concatenation end return format; end --[[---------------------< G E T _ D I S P L A Y _ N A M E S >------------------ Returns a number that defines the number of names displayed for author and editor name lists and a Boolean flag to indicate when et al. should be appended to the name list. When the value assigned to |display-xxxxors= is a number greater than or equal to zero, return the number and the previous state of the 'etal' flag (false by default but may have been set to true if the name list contains some variant of the text 'et al.'). When the value assigned to |display-xxxxors= is the keyword 'etal', return a number that is one greater than the number of authors in the list and set the 'etal' flag true. This will cause the list_people() to display all of the names in the name list followed by 'et al.' In all other cases, returns nil and the previous state of the 'etal' flag. inputs: max: A['DisplayAuthors'] or A['DisplayEditors']; a number or some flavor of etal count: #a or #e list_name: 'authors' or 'editors' etal: author_etal or editor_etal ]] local function get_display_names (max, count, list_name, etal, param) if utilities.is_set (max) then if 'etal' == max:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings max = count + 1; -- number of authors + 1 so display all author name plus et al. etal = true; -- overrides value set by extract_names() elseif max:match ('^%d+$') then -- if is a string of numbers max = tonumber (max); -- make it a number if max >= count then -- if |display-xxxxors= value greater than or equal to number of authors/editors utilities.set_message ('err_disp_name', {param, max}); -- add error message max = nil; end else -- not a valid keyword or number utilities.set_message ('err_disp_name', {param, max}); -- add error message max = nil; -- unset; as if |display-xxxxors= had not been set end end return max, etal; end --[[----------< E X T R A _ T E X T _ I N _ P A G E _ C H E C K >--------------- Adds error if |page=, |pages=, |quote-page=, |quote-pages= has what appears to be some form of p. or pp. abbreviation in the first characters of the parameter content. check page for extraneous p, p., pp, pp., pg, pg. at start of parameter value: good pattern: '^P[^%.P%l]' matches when page begins PX or P# but not Px where x and X are letters and # is a digit bad pattern: '^[Pp][PpGg]' matches when page begins pp, pP, Pp, PP, pg, pG, Pg, PG ]] local function extra_text_in_page_check (val, name) if not val:match (cfg.vol_iss_pg_patterns.good_ppattern) then for _, pattern in ipairs (cfg.vol_iss_pg_patterns.bad_ppatterns) do -- spin through the selected sequence table of patterns if val:match (pattern) then -- when a match, error so utilities.set_message ('err_extra_text_pages', name); -- add error message return; -- and done end end end end --[[--------------------------< E X T R A _ T E X T _ I N _ V O L _ I S S _ C H E C K >------------------------ Adds error if |volume= or |issue= has what appears to be some form of redundant 'type' indicator. For |volume=: 'V.', or 'Vol.' (with or without the dot) abbreviations or 'Volume' in the first characters of the parameter content (all case insensitive). 'V' and 'v' (without the dot) are presumed to be roman numerals so are allowed. For |issue=: 'No.', 'I.', 'Iss.' (with or without the dot) abbreviations, or 'Issue' in the first characters of the parameter content (all case insensitive). Single character values ('v', 'i', 'n') allowed when not followed by separator character ('.', ':', '=', or whitespace character) – param values are trimmed of whitespace by MediaWiki before delivered to the module. <val> is |volume= or |issue= parameter value <name> is |volume= or |issue= parameter name for error message <selector> is 'v' for |volume=, 'i' for |issue= sets error message on failure; returns nothing ]] local function extra_text_in_vol_iss_check (val, name, selector) if not utilities.is_set (val) then return; end local patterns = 'v' == selector and cfg.vol_iss_pg_patterns.vpatterns or cfg.vol_iss_pg_patterns.ipatterns; local handler = 'v' == selector and 'err_extra_text_volume' or 'err_extra_text_issue'; val = val:lower(); -- force parameter value to lower case for _, pattern in ipairs (patterns) do -- spin through the selected sequence table of patterns if val:match (pattern) then -- when a match, error so utilities.set_message (handler, name); -- add error message return; -- and done end end end --[=[-------------------------< G E T _ V _ N A M E _ T A B L E >---------------------------------------------- split apart a |vauthors= or |veditors= parameter. This function allows for corporate names, wrapped in doubled parentheses to also have commas; in the old version of the code, the doubled parentheses were included in the rendered citation and in the metadata. Individual author names may be wikilinked |vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.)) ]=] local function get_v_name_table (vparam, output_table, output_link_table) local name_table = mw.text.split(vparam, "%s*,%s*"); -- names are separated by commas local wl_type, label, link; -- wl_type not used here; just a placeholder local i = 1; while name_table[i] do if name_table[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses local name = name_table[i]; i = i + 1; -- bump indexer to next segment while name_table[i] do name = name .. ', ' .. name_table[i]; -- concatenate with previous segments if name_table[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parentheses break; -- and done reassembling so end i = i + 1; -- bump indexer end table.insert (output_table, name); -- and add corporate name to the output table table.insert (output_link_table, ''); -- no wikilink else wl_type, label, link = utilities.is_wikilink (name_table[i]); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]] table.insert (output_table, label); -- add this name if 1 == wl_type then table.insert (output_link_table, label); -- simple wikilink [[D]] else table.insert (output_link_table, link); -- no wikilink or [[L|D]]; add this link if there is one, else empty string end end i = i + 1; end return output_table; end --[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- This function extracts author / editor names from |vauthors= or |veditors= and finds matching |xxxxor-maskn= and |xxxxor-linkn= in args. It then returns a table of assembled names just as extract_names() does. Author / editor names in |vauthors= or |veditors= must be in Vancouver system style. Corporate or institutional names may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance tests, are wrapped in doubled parentheses ((corporate name)) to suppress the format tests. Supports generational suffixes Jr, 2nd, 3rd, 4th–6th. This function sets the Vancouver error when a required comma is missing and when there is a space between an author's initials. ]] local function parse_vauthors_veditors (args, vparam, list_name) local names = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn= local v_name_table = {}; local v_link_table = {}; -- when name is wikilinked, targets go in this table local etal = false; -- return value set to true when we find some form of et al. vauthors parameter local last, first, link, mask, suffix; local corporate = false; vparam, etal = name_has_etal (vparam, etal, true); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period) v_name_table = get_v_name_table (vparam, v_name_table, v_link_table); -- names are separated by commas for i, v_name in ipairs(v_name_table) do first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor local accept_name; v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name> if accept_name then last = v_name; corporate = true; -- flag used in list_people() elseif string.find(v_name, "%s") then if v_name:find('[;%.]') then -- look for commonly occurring punctuation characters; add_vanc_error (cfg.err_msg_supl.punctuation, i); end local lastfirstTable = {} lastfirstTable = mw.text.split(v_name, "%s+") first = table.remove(lastfirstTable); -- removes and returns value of last element in table which should be initials or generational suffix if not mw.ustring.match (first, '^%u+$') then -- mw.ustring here so that later we will catch non-Latin characters suffix = first; -- not initials so assume that whatever we got is a generational suffix first = table.remove(lastfirstTable); -- get what should be the initials from the table end last = table.concat(lastfirstTable, ' ') -- returns a string that is the concatenation of all other names that are not initials and generational suffix if not utilities.is_set (last) then first = ''; -- unset last = v_name; -- last empty because something wrong with first add_vanc_error (cfg.err_msg_supl.name, i); end if mw.ustring.match (last, '%a+%s+%u+%s+%a+') then add_vanc_error (cfg.err_msg_supl['missing comma'], i); -- matches last II last; the case when a comma is missing end if mw.ustring.match (v_name, ' %u %u$') then -- this test is in the wrong place TODO: move or replace with a more appropriate test add_vanc_error (cfg.err_msg_supl.initials, i); -- matches a space between two initials end else last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this? end if utilities.is_set (first) then if not mw.ustring.match (first, "^%u?%u$") then -- first shall contain one or two upper-case letters, nothing else add_vanc_error (cfg.err_msg_supl.initials, i); -- too many initials; mixed case initials (which may be ok Romanization); hyphenated initials end is_good_vanc_name (last, first, suffix, i); -- check first and last before restoring the suffix which may have a non-Latin digit if utilities.is_set (suffix) then first = first .. ' ' .. suffix; -- if there was a suffix concatenate with the initials suffix = ''; -- unset so we don't add this suffix to all subsequent names end else if not corporate then is_good_vanc_name (last, '', nil, i); end end link = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ) or v_link_table[i]; mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i ); names[i] = {last = last, first = first, link = link, mask = mask, corporate = corporate}; -- add this assembled name to our names list end return names, etal; -- all done, return our list of names end --[[--------------------------< S E L E C T _ A U T H O R _ E D I T O R _ S O U R C E >------------------------ Select one of |authors=, |authorn= / |lastn / firstn=, or |vauthors= as the source of the author name list or select one of |editorn= / editor-lastn= / |editor-firstn= or |veditors= as the source of the editor name list. Only one of these appropriate three will be used. The hierarchy is: |authorn= (and aliases) highest and |authors= lowest; |editorn= (and aliases) highest and |veditors= lowest (support for |editors= withdrawn) When looking for |authorn= / |editorn= parameters, test |xxxxor1= and |xxxxor2= (and all of their aliases); stops after the second test which mimicks the test used in extract_names() when looking for a hole in the author name list. There may be a better way to do this, I just haven't discovered what that way is. Emits an error message when more than one xxxxor name source is provided. In this function, vxxxxors = vauthors or veditors; xxxxors = authors as appropriate. ]] local function select_author_editor_source (vxxxxors, xxxxors, args, list_name) local lastfirst = false; if utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice in case we have a |first1= without a |last1=; this ... utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'none', 1 ) or -- ... also catches the case where |first= is used with |vauthors= utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'none', 2 ) or utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'none', 2 ) then lastfirst = true; end if (utilities.is_set (vxxxxors) and true == lastfirst) or -- these are the three error conditions (utilities.is_set (vxxxxors) and utilities.is_set (xxxxors)) or (true == lastfirst and utilities.is_set (xxxxors)) then local err_name; if 'AuthorList' == list_name then -- figure out which name should be used in error message err_name = 'author'; else err_name = 'editor'; end utilities.set_message ('err_redundant_parameters', err_name .. '-name-list parameters'); -- add error message end if true == lastfirst then return 1 end; -- return a number indicating which author name source to use if utilities.is_set (vxxxxors) then return 2 end; if utilities.is_set (xxxxors) then return 3 end; return 1; -- no authors so return 1; this allows missing author name test to run in case there is a first without last end --[[--------------------------< I S _ V A L I D _ P A R A M E T E R _ V A L U E >------------------------------ This function is used to validate a parameter's assigned value for those parameters that have only a limited number of allowable values (yes, y, true, live, dead, etc.). When the parameter value has not been assigned a value (missing or empty in the source template) the function returns the value specified by ret_val. If the parameter value is one of the list of allowed values returns the translated value; else, emits an error message and returns the value specified by ret_val. TODO: explain <invert> ]] local function is_valid_parameter_value (value, name, possible, ret_val, invert) if not utilities.is_set (value) then return ret_val; -- an empty parameter is ok end if (not invert and utilities.in_array (value, possible)) then -- normal; <value> is in <possible> table return cfg.keywords_xlate[value]; -- return translation of parameter keyword elseif invert and not utilities.in_array (value, possible) then -- invert; <value> is not in <possible> table return value; -- return <value> as it is else utilities.set_message ('err_invalid_param_val', {name, value}); -- not an allowed value so add error message return ret_val; end end --[[--------------------------< T E R M I N A T E _ N A M E _ L I S T >---------------------------------------- This function terminates a name list (author, contributor, editor) with a separator character (sepc) and a space when the last character is not a sepc character or when the last three characters are not sepc followed by two closing square brackets (close of a wikilink). When either of these is true, the name_list is terminated with a single space character. ]] local function terminate_name_list (name_list, sepc) if (string.sub (name_list, -3, -1) == sepc .. '. ') then -- if already properly terminated return name_list; -- just return the name list elseif (string.sub (name_list, -1, -1) == sepc) or (string.sub (name_list, -3, -1) == sepc .. ']]') then -- if last name in list ends with sepc char return name_list .. " "; -- don't add another else return name_list .. sepc .. ' '; -- otherwise terminate the name list end end --[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >---------------------------------------- returns the concatenation of the formatted volume and issue parameters as a single string; or formatted volume or formatted issue, or an empty string if neither are set. ]] local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower) if not utilities.is_set (volume) and not utilities.is_set (issue) then return ''; end -- same condition as in format_pages_sheets() local is_journal = 'journal' == cite_class or (utilities.in_array (cite_class, {'citation', 'map', 'interview'}) and 'journal' == origin); local is_numeric_vol = volume and (volume:match ('^[MDCLXVI]+$') or volume:match ('^%d+$')); -- is only uppercase roman numerals or only digits? local is_long_vol = volume and (4 < mw.ustring.len(volume)); -- is |volume= value longer than 4 characters? if volume and (not is_numeric_vol and is_long_vol) then -- when not all digits or Roman numerals, is |volume= longer than 4 characters? utilities.add_prop_cat ('long-vol'); -- yes, add properties cat end if is_journal then -- journal-style formatting local vol = ''; if utilities.is_set (volume) then if is_numeric_vol then -- |volume= value all digits or all uppercase Roman numerals? vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, volume}); -- render in bold face elseif is_long_vol then -- not all digits or Roman numerals; longer than 4 characters? vol = utilities.substitute (cfg.messages['j-vol'], {sepc, utilities.hyphen_to_dash (volume)}); -- not bold else -- four or fewer characters vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, utilities.hyphen_to_dash (volume)}); -- bold end end if utilities.is_set (issue) then return vol .. utilities.substitute (cfg.messages['j-issue'], issue); end return vol; end if 'podcast' == cite_class and utilities.is_set (issue) then return wrap_msg ('issue', {sepc, issue}, lower); end -- all other types of citation if utilities.is_set (volume) and utilities.is_set (issue) then return wrap_msg ('vol-no', {sepc, utilities.hyphen_to_dash (volume), issue}, lower); elseif utilities.is_set (volume) then return wrap_msg ('vol', {sepc, utilities.hyphen_to_dash (volume)}, lower); else return wrap_msg ('issue', {sepc, issue}, lower); end end --[[-------------------------< F O R M A T _ P A G E S _ S H E E T S >----------------------------------------- adds static text to one of |page(s)= or |sheet(s)= values and returns it with all of the others set to empty strings. The return order is: page, pages, sheet, sheets Singular has priority over plural when both are provided. ]] local function format_pages_sheets (page, pages, sheet, sheets, cite_class, origin, sepc, nopp, lower) if 'map' == cite_class then -- only cite map supports sheet(s) as in-source locators if utilities.is_set (sheet) then if 'journal' == origin then return '', '', wrap_msg ('j-sheet', sheet, lower), ''; else return '', '', wrap_msg ('sheet', {sepc, sheet}, lower), ''; end elseif utilities.is_set (sheets) then if 'journal' == origin then return '', '', '', wrap_msg ('j-sheets', sheets, lower); else return '', '', '', wrap_msg ('sheets', {sepc, sheets}, lower); end end end local is_journal = 'journal' == cite_class or (utilities.in_array (cite_class, {'citation', 'map', 'interview'}) and 'journal' == origin); if utilities.is_set (page) then if is_journal then return utilities.substitute (cfg.messages['j-page(s)'], page), '', '', ''; elseif not nopp then return utilities.substitute (cfg.messages['p-prefix'], {sepc, page}), '', '', ''; else return utilities.substitute (cfg.messages['nopp'], {sepc, page}), '', '', ''; end elseif utilities.is_set (pages) then if is_journal then return utilities.substitute (cfg.messages['j-page(s)'], pages), '', '', ''; elseif tonumber(pages) ~= nil and not nopp then -- if pages is only digits, assume a single page number return '', utilities.substitute (cfg.messages['p-prefix'], {sepc, pages}), '', ''; elseif not nopp then return '', utilities.substitute (cfg.messages['pp-prefix'], {sepc, pages}), '', ''; else return '', utilities.substitute (cfg.messages['nopp'], {sepc, pages}), '', ''; end end return '', '', '', ''; -- return empty strings end --[[--------------------------< I N S O U R C E _ L O C _ G E T >---------------------------------------------- returns one of the in-source locators: page, pages, or at. If any of these are interwiki links to Wikisource, returns the label portion of the interwiki-link as plain text for use in COinS. This COinS thing is done because here we convert an interwiki-link to an external link and add an icon span around that; get_coins_pages() doesn't know about the span. TODO: should it? TODO: add support for sheet and sheets?; streamline; TODO: make it so that this function returns only one of the three as the single in-source (the return value assigned to a new name)? ]] local function insource_loc_get (page, page_orig, pages, pages_orig, at) local ws_url, ws_label, coins_pages, L; -- for Wikisource interwiki-links; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?) if utilities.is_set (page) then if utilities.is_set (pages) or utilities.is_set (at) then pages = ''; -- unset the others at = ''; end extra_text_in_page_check (page, page_orig); -- emit error message when |page= value begins with what looks like p., pp., etc. ws_url, ws_label, L = wikisource_url_make (page); -- make ws URL from |page= interwiki link; link portion L becomes tooltip label if ws_url then page = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in page'); -- space char after label to move icon away from in-source text; TODO: a better way to do this? page = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, page}); coins_pages = ws_label; end elseif utilities.is_set (pages) then if utilities.is_set (at) then at = ''; -- unset end extra_text_in_page_check (pages, pages_orig); -- emit error message when |page= value begins with what looks like p., pp., etc. ws_url, ws_label, L = wikisource_url_make (pages); -- make ws URL from |pages= interwiki link; link portion L becomes tooltip label if ws_url then pages = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in pages'); -- space char after label to move icon away from in-source text; TODO: a better way to do this? pages = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, pages}); coins_pages = ws_label; end elseif utilities.is_set (at) then ws_url, ws_label, L = wikisource_url_make (at); -- make ws URL from |at= interwiki link; link portion L becomes tooltip label if ws_url then at = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in at'); -- space char after label to move icon away from in-source text; TODO: a better way to do this? at = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, at}); coins_pages = ws_label; end end return page, pages, at, coins_pages; end --[[--------------------------< I S _ U N I Q U E _ A R C H I V E _ U R L >------------------------------------ add error message when |archive-url= value is same as |url= or chapter-url= (or alias...) value ]] local function is_unique_archive_url (archive, url, c_url, source, date) if utilities.is_set (archive) then if archive == url or archive == c_url then utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}); -- add error message return '', ''; -- unset |archive-url= and |archive-date= because same as |url= or |chapter-url= end end return archive, date; end --[=[-------------------------< A R C H I V E _ U R L _ C H E C K >-------------------------------------------- Check archive.org URLs to make sure they at least look like they are pointing at valid archives and not to the save snapshot URL or to calendar pages. When the archive URL is 'https://web.archive.org/save/' (or http://...) archive.org saves a snapshot of the target page in the URL. That is something that Wikipedia should not allow unwitting readers to do. When the archive.org URL does not have a complete timestamp, archive.org chooses a snapshot according to its own algorithm or provides a calendar 'search' result. [[WP:ELNO]] discourages links to search results. This function looks at the value assigned to |archive-url= and returns empty strings for |archive-url= and |archive-date= and an error message when: |archive-url= holds an archive.org save command URL |archive-url= is an archive.org URL that does not have a complete timestamp (YYYYMMDDhhmmss 14 digits) in the correct place otherwise returns |archive-url= and |archive-date= There are two mostly compatible archive.org URLs: //web.archive.org/<timestamp>... -- the old form //web.archive.org/web/<timestamp>... -- the new form The old form does not support or map to the new form when it contains a display flag. There are four identified flags ('id_', 'js_', 'cs_', 'im_') but since archive.org ignores others following the same form (two letters and an underscore) we don't check for these specific flags but we do check the form. This function supports a preview mode. When the article is rendered in preview mode, this function may return a modified archive URL: for save command errors, return undated wildcard (/*/) for timestamp errors when the timestamp has a wildcard, return the URL unmodified for timestamp errors when the timestamp does not have a wildcard, return with timestamp limited to six digits plus wildcard (/yyyymm*/) ]=] local function archive_url_check (url, date) local err_msg = ''; -- start with the error message empty local path, timestamp, flag; -- portions of the archive.org URL if (not url:match('//web%.archive%.org/')) and (not url:match('//liveweb%.archive%.org/')) then -- also deprecated liveweb Wayback machine URL return url, date; -- not an archive.org archive, return ArchiveURL and ArchiveDate end if url:match('//web%.archive%.org/save/') then -- if a save command URL, we don't want to allow saving of the target page err_msg = cfg.err_msg_supl.save; url = url:gsub ('(//web%.archive%.org)/save/', '%1/*/', 1); -- for preview mode: modify ArchiveURL elseif url:match('//liveweb%.archive%.org/') then err_msg = cfg.err_msg_supl.liveweb; else path, timestamp, flag = url:match('//web%.archive%.org/([^%d]*)(%d+)([^/]*)/'); -- split out some of the URL parts for evaluation if not path then -- malformed in some way; pattern did not match err_msg = cfg.err_msg_supl.timestamp; elseif 14 ~= timestamp:len() then -- path and flag optional, must have 14-digit timestamp here err_msg = cfg.err_msg_supl.timestamp; if '*' ~= flag then local replacement = timestamp:match ('^%d%d%d%d%d%d') or timestamp:match ('^%d%d%d%d'); -- get the first 6 (YYYYMM) or first 4 digits (YYYY) if replacement then -- nil if there aren't at least 4 digits (year) replacement = replacement .. string.rep ('0', 14 - replacement:len()); -- year or yearmo (4 or 6 digits) zero-fill to make 14-digit timestamp url=url:gsub ('(//web%.archive%.org/[^%d]*)%d[^/]*', '%1' .. replacement .. '*', 1) -- for preview, modify ts to 14 digits plus splat for calendar display end end elseif utilities.is_set (path) and 'web/' ~= path then -- older archive URLs do not have the extra 'web/' path element err_msg = cfg.err_msg_supl.path; elseif utilities.is_set (flag) and not utilities.is_set (path) then -- flag not allowed with the old form URL (without the 'web/' path element) err_msg = cfg.err_msg_supl.flag; elseif utilities.is_set (flag) and not flag:match ('%a%a_') then -- flag if present must be two alpha characters and underscore (requires 'web/' path element) err_msg = cfg.err_msg_supl.flag; else return url, date; -- return ArchiveURL and ArchiveDate end end -- if here, something not right so utilities.set_message ('err_archive_url', {err_msg}); -- add error message and if is_preview_mode then return url, date; -- preview mode so return ArchiveURL and ArchiveDate else return '', ''; -- return empty strings for ArchiveURL and ArchiveDate end end --[[--------------------------< P L A C E _ C H E C K >-------------------------------------------------------- check |place=, |publication-place=, |location= to see if these params include digits. This function added because many editors misuse location to specify the in-source location (|page(s)= and |at= are supposed to do that) returns the original parameter value without modification; added maint cat when parameter value contains digits ]] local function place_check (param_val) if not utilities.is_set (param_val) then -- parameter empty or omitted return param_val; -- return that empty state end if mw.ustring.find (param_val, '%d') then -- not empty, are there digits in the parameter value utilities.set_message ('maint_location'); -- yep, add maint cat end return param_val; -- and done end --[[--------------------------< I S _ A R C H I V E D _ C O P Y >---------------------------------------------- compares |title= to 'Archived copy' (placeholder added by bots that can't find proper title); if matches, return true; nil else ]] local function is_archived_copy (title) title = mw.ustring.lower(title); -- switch title to lower case if title:find (cfg.special_case_translation.archived_copy.en) then -- if title is 'Archived copy' return true; elseif cfg.special_case_translation.archived_copy['local'] then if mw.ustring.find (title, cfg.special_case_translation.archived_copy['local']) then -- mw.ustring() because might not be Latin script return true; end end end --[[--------------------------< C I T A T I O N 0 >------------------------------------------------------------ This is the main function doing the majority of the citation formatting. ]] local function citation0( config, args ) --[[ Load Input Parameters The argument_wrapper facilitates the mapping of multiple aliases to single internal variable. ]] local A = argument_wrapper ( args ); local i -- Pick out the relevant fields from the arguments. Different citation templates -- define different field names for the same underlying things. local author_etal; local a = {}; -- authors list from |lastn= / |firstn= pairs or |vauthors= local Authors; local NameListStyle = is_valid_parameter_value (A['NameListStyle'], A:ORIGIN('NameListStyle'), cfg.keywords_lists['name-list-style'], ''); local Collaboration = A['Collaboration']; do -- to limit scope of selected local selected = select_author_editor_source (A['Vauthors'], A['Authors'], args, 'AuthorList'); if 1 == selected then a, author_etal = extract_names (args, 'AuthorList'); -- fetch author list from |authorn= / |lastn= / |firstn=, |author-linkn=, and |author-maskn= elseif 2 == selected then NameListStyle = 'vanc'; -- override whatever |name-list-style= might be a, author_etal = parse_vauthors_veditors (args, args.vauthors, 'AuthorList'); -- fetch author list from |vauthors=, |author-linkn=, and |author-maskn= elseif 3 == selected then Authors = A['Authors']; -- use content of |authors= if 'authors' == A:ORIGIN('Authors') then -- but add a maint cat if the parameter is |authors= utilities.set_message ('maint_authors'); -- because use of this parameter is discouraged; what to do about the aliases is a TODO: end end if utilities.is_set (Collaboration) then author_etal = true; -- so that |display-authors=etal not required end end local editor_etal; local e = {}; -- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors= do -- to limit scope of selected local selected = select_author_editor_source (A['Veditors'], nil, args, 'EditorList'); -- support for |editors= withdrawn if 1 == selected then e, editor_etal = extract_names (args, 'EditorList'); -- fetch editor list from |editorn= / |editor-lastn= / |editor-firstn=, |editor-linkn=, and |editor-maskn= elseif 2 == selected then NameListStyle = 'vanc'; -- override whatever |name-list-style= might be e, editor_etal = parse_vauthors_veditors (args, args.veditors, 'EditorList'); -- fetch editor list from |veditors=, |editor-linkn=, and |editor-maskn= end end local Chapter = A['Chapter']; -- done here so that we have access to |contribution= from |chapter= aliases local Chapter_origin = A:ORIGIN ('Chapter'); local Contribution; -- because contribution is required for contributor(s) if 'contribution' == Chapter_origin then Contribution = Chapter; -- get the name of the contribution end local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (A['Periodical']) then -- |contributor= and |contribution= only supported in book cites c = extract_names (args, 'ContributorList'); -- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn= if 0 < #c then if not utilities.is_set (Contribution) then -- |contributor= requires |contribution= utilities.set_message ('err_contributor_missing_required_param', 'contribution'); -- add missing contribution error message c = {}; -- blank the contributors' table; it is used as a flag later end if 0 == #a then -- |contributor= requires |author= utilities.set_message ('err_contributor_missing_required_param', 'author'); -- add missing author error message c = {}; -- blank the contributors' table; it is used as a flag later end end else -- if not a book cite if utilities.select_one (args, cfg.aliases['ContributorList-Last'], 'err_redundant_parameters', 1 ) then -- are there contributor name list parameters? utilities.set_message ('err_contributor_ignored'); -- add contributor ignored error message end Contribution = nil; -- unset end local Title = A['Title']; local TitleLink = A['TitleLink']; local auto_select = ''; -- default is auto local accept_link; TitleLink, accept_link = utilities.has_accept_as_written (TitleLink, true); -- test for accept-this-as-written markup if (not accept_link) and utilities.in_array (TitleLink, {'none', 'pmc', 'doi'}) then -- check for special keywords auto_select = TitleLink; -- remember selection for later TitleLink = ''; -- treat as if |title-link= would have been empty end TitleLink = link_title_ok (TitleLink, A:ORIGIN ('TitleLink'), Title, 'title'); -- check for wiki-markup in |title-link= or wiki-markup in |title= when |title-link= is set local Section = ''; -- {{cite map}} only; preset to empty string for concatenation if not used if 'map' == config.CitationClass and 'section' == Chapter_origin then Section = A['Chapter']; -- get |section= from |chapter= alias list; |chapter= and the other aliases not supported in {{cite map}} Chapter = ''; -- unset for now; will be reset later from |map= if present end local Periodical = A['Periodical']; local Periodical_origin = ''; if utilities.is_set (Periodical) then Periodical_origin = A:ORIGIN('Periodical'); -- get the name of the periodical parameter local i; Periodical, i = utilities.strip_apostrophe_markup (Periodical); -- strip apostrophe markup so that metadata isn't contaminated if i then -- non-zero when markup was stripped so emit an error message utilities.set_message ('err_apostrophe_markup', {Periodical_origin}); end end if 'mailinglist' == config.CitationClass then -- special case for {{cite mailing list}} if utilities.is_set (Periodical) and utilities.is_set (A ['MailingList']) then -- both set emit an error TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. ' and ' .. utilities.wrap_style ('parameter', 'mailinglist')}); end Periodical = A ['MailingList']; -- error or no, set Periodical to |mailinglist= value because this template is {{cite mailing list}} Periodical_origin = A:ORIGIN('MailingList'); end local ScriptPeriodical = A['ScriptPeriodical']; -- web and news not tested for now because of -- Wikipedia:Administrators%27_noticeboard#Is_there_a_semi-automated_tool_that_could_fix_these_annoying_"Cite_Web"_errors? if not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) then -- 'periodical' templates require periodical parameter -- local p = {['journal'] = 'journal', ['magazine'] = 'magazine', ['news'] = 'newspaper', ['web'] = 'website'}; -- for error message local p = {['journal'] = 'journal', ['magazine'] = 'magazine'}; -- for error message if p[config.CitationClass] then utilities.set_message ('err_missing_periodical', {config.CitationClass, p[config.CitationClass]}); end end local Volume; local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical'); if 'citation' == config.CitationClass then if utilities.is_set (Periodical) then if not utilities.in_array (Periodical_origin, cfg.citation_no_volume_t) then -- {{citation}} does not render |volume= when these parameters are used Volume = A['Volume']; -- but does for all other 'periodicals' end elseif utilities.is_set (ScriptPeriodical) then if 'script-website' ~= ScriptPeriodical_origin then -- {{citation}} does not render volume for |script-website= Volume = A['Volume']; -- but does for all other 'periodicals' end else Volume = A['Volume']; -- and does for non-'periodical' cites end elseif utilities.in_array (config.CitationClass, cfg.templates_using_volume) then -- render |volume= for cs1 according to the configuration settings Volume = A['Volume']; end extra_text_in_vol_iss_check (Volume, A:ORIGIN ('Volume'), 'v'); local Issue; if 'citation' == config.CitationClass then if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, cfg.citation_issue_t) then -- {{citation}} may render |issue= when these parameters are used Issue = utilities.hyphen_to_dash (A['Issue']); end elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then -- conference & map books do not support issue; {{citation}} listed here because included in settings table if not (utilities.in_array (config.CitationClass, {'conference', 'map', 'citation'}) and not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical))) then Issue = utilities.hyphen_to_dash (A['Issue']); end end extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i'); local Page; local Pages; local At; if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then Page = A['Page']; Pages = utilities.hyphen_to_dash (A['Pages']); At = A['At']; end local Edition = A['Edition']; local PublicationPlace = place_check (A['PublicationPlace'], A:ORIGIN('PublicationPlace')); local Place = place_check (A['Place'], A:ORIGIN('Place')); local PublisherName = A['PublisherName']; local PublisherName_origin = A:ORIGIN('PublisherName'); if utilities.is_set (PublisherName) then local i = 0; PublisherName, i = utilities.strip_apostrophe_markup (PublisherName); -- strip apostrophe markup so that metadata isn't contaminated; publisher is never italicized if i then -- non-zero when markup was stripped so emit an error message utilities.set_message ('err_apostrophe_markup', {PublisherName_origin}); end end local Newsgroup = A['Newsgroup']; -- TODO: strip apostrophe markup? local Newsgroup_origin = A:ORIGIN('Newsgroup'); if 'newsgroup' == config.CitationClass then if utilities.is_set (PublisherName) then -- general use parameter |publisher= not allowed in cite newsgroup utilities.set_message ('err_parameter_ignored', {PublisherName_origin}); end PublisherName = nil; -- ensure that this parameter is unset for the time being; will be used again after COinS end local URL = A['URL']; -- TODO: better way to do this for URL, ChapterURL, and MapURL? local UrlAccess = is_valid_parameter_value (A['UrlAccess'], A:ORIGIN('UrlAccess'), cfg.keywords_lists['url-access'], nil); if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then UrlAccess = nil; utilities.set_message ('err_param_access_requires_param', 'url'); end local ChapterURL = A['ChapterURL']; local ChapterUrlAccess = is_valid_parameter_value (A['ChapterUrlAccess'], A:ORIGIN('ChapterUrlAccess'), cfg.keywords_lists['url-access'], nil); if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then ChapterUrlAccess = nil; utilities.set_message ('err_param_access_requires_param', {A:ORIGIN('ChapterUrlAccess'):gsub ('%-access', '')}); end local MapUrlAccess = is_valid_parameter_value (A['MapUrlAccess'], A:ORIGIN('MapUrlAccess'), cfg.keywords_lists['url-access'], nil); if not utilities.is_set (A['MapURL']) and utilities.is_set (MapUrlAccess) then MapUrlAccess = nil; utilities.set_message ('err_param_access_requires_param', {'map-url'}); end local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language local no_tracking_cats = is_valid_parameter_value (A['NoTracking'], A:ORIGIN('NoTracking'), cfg.keywords_lists['yes_true_y'], nil); -- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories if not utilities.is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page if utilities.in_array (this_page.nsText, cfg.uncategorized_namespaces) then no_tracking_cats = "true"; -- set no_tracking_cats end for _, v in ipairs (cfg.uncategorized_subpages) do -- cycle through page name patterns if this_page.text:match (v) then -- test page name against each pattern no_tracking_cats = "true"; -- set no_tracking_cats break; -- bail out if one is found end end end -- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we're at it) utilities.select_one (args, {'page', 'p', 'pp', 'pages', 'at', 'sheet', 'sheets'}, 'err_redundant_parameters'); -- this is a dummy call simply to get the error message and category local coins_pages; Page, Pages, At, coins_pages = insource_loc_get (Page, A:ORIGIN('Page'), Pages, A:ORIGIN('Pages'), At); local NoPP = is_valid_parameter_value (A['NoPP'], A:ORIGIN('NoPP'), cfg.keywords_lists['yes_true_y'], nil); if utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- both |publication-place= and |place= (|location=) allowed if different utilities.add_prop_cat ('location-test'); -- add property cat to evaluate how often PublicationPlace and Place are used together if PublicationPlace == Place then Place = ''; -- unset; don't need both if they are the same end elseif not utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- when only |place= (|location=) is set ... PublicationPlace = Place; -- promote |place= (|location=) to |publication-place end if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same local URL_origin = A:ORIGIN('URL'); -- get name of parameter that holds URL local ChapterURL_origin = A:ORIGIN('ChapterURL'); -- get name of parameter that holds ChapterURL local ScriptChapter = A['ScriptChapter']; local ScriptChapter_origin = A:ORIGIN ('ScriptChapter'); local Format = A['Format']; local ChapterFormat = A['ChapterFormat']; local TransChapter = A['TransChapter']; local TransChapter_origin = A:ORIGIN ('TransChapter'); local TransTitle = A['TransTitle']; local ScriptTitle = A['ScriptTitle']; --[[ Parameter remapping for cite encyclopedia: When the citation has these parameters: |encyclopedia= and |title= then map |title= to |article= and |encyclopedia= to |title= |encyclopedia= and |article= then map |encyclopedia= to |title= |trans-title= maps to |trans-chapter= when |title= is re-mapped |url= maps to |chapter-url= when |title= is remapped All other combinations of |encyclopedia=, |title=, and |article= are not modified ]] local Encyclopedia = A['Encyclopedia']; -- used as a flag by this module and by ~/COinS if utilities.is_set (Encyclopedia) then -- emit error message when Encyclopedia set but template is other than {{cite encyclopedia}} or {{citation}} if 'encyclopaedia' ~= config.CitationClass and 'citation' ~= config.CitationClass then utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('Encyclopedia')}); Encyclopedia = nil; -- unset because not supported by this template end end if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both set emit an error TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', A:ORIGIN ('Encyclopedia')) .. ' and ' .. utilities.wrap_style ('parameter', Periodical_origin)}); end if utilities.is_set (Encyclopedia) then Periodical = Encyclopedia; -- error or no, set Periodical to Encyclopedia; allow periodical without encyclopedia Periodical_origin = A:ORIGIN ('Encyclopedia'); end if utilities.is_set (Periodical) then -- Periodical is set when |encyclopedia= is set if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then if not utilities.is_set (Chapter) then Chapter = Title; -- |encyclopedia= and |title= are set so map |title= to |article= and |encyclopedia= to |title= ScriptChapter = ScriptTitle; ScriptChapter_origin = A:ORIGIN('ScriptTitle') TransChapter = TransTitle; ChapterURL = URL; ChapterURL_origin = URL_origin; ChapterUrlAccess = UrlAccess; if not utilities.is_set (ChapterURL) and utilities.is_set (TitleLink) then Chapter = utilities.make_wikilink (TitleLink, Chapter); end Title = Periodical; ChapterFormat = Format; Periodical = ''; -- redundant so unset TransTitle = ''; URL = ''; Format = ''; TitleLink = ''; ScriptTitle = ''; end elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then -- |title= not set Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= Periodical = ''; -- redundant so unset end end end -- special case for cite techreport. local ID = A['ID']; if (config.CitationClass == "techreport") then -- special case for cite techreport if utilities.is_set (A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue' if not utilities.is_set (ID) then -- can we use ID for the "number"? ID = A['Number']; -- yes, use it else -- ID has a value so emit error message utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. ' and ' .. utilities.wrap_style ('parameter', 'number')}); end end end -- Account for the oddity that is {{cite conference}}, before generation of COinS data. local ChapterLink -- = A['ChapterLink']; -- deprecated as a parameter but still used internally by cite episode local Conference = A['Conference']; local BookTitle = A['BookTitle']; local TransTitle_origin = A:ORIGIN ('TransTitle'); if 'conference' == config.CitationClass then if utilities.is_set (BookTitle) then Chapter = Title; Chapter_origin = 'title'; -- ChapterLink = TitleLink; -- |chapter-link= is deprecated ChapterURL = URL; ChapterUrlAccess = UrlAccess; ChapterURL_origin = URL_origin; URL_origin = ''; ChapterFormat = Format; TransChapter = TransTitle; TransChapter_origin = TransTitle_origin; Title = BookTitle; Format = ''; -- TitleLink = ''; TransTitle = ''; URL = ''; end elseif 'speech' ~= config.CitationClass then Conference = ''; -- not cite conference or cite speech so make sure this is empty string end -- CS1/2 mode local Mode = is_valid_parameter_value (A['Mode'], A:ORIGIN('Mode'), cfg.keywords_lists['mode'], ''); -- separator character and postscript local sepc, PostScript = set_style (Mode:lower(), A['PostScript'], config.CitationClass); -- controls capitalization of certain static text local use_lowercase = ( sepc == ',' ); -- cite map oddities local Cartography = ""; local Scale = ""; local Sheet = A['Sheet'] or ''; local Sheets = A['Sheets'] or ''; if config.CitationClass == "map" then if utilities.is_set (Chapter) then --TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. ' and ' .. utilities.wrap_style ('parameter', Chapter_origin)}); -- add error message end Chapter = A['Map']; Chapter_origin = A:ORIGIN('Map'); ChapterURL = A['MapURL']; ChapterURL_origin = A:ORIGIN('MapURL'); TransChapter = A['TransMap']; ScriptChapter = A['ScriptMap'] ScriptChapter_origin = A:ORIGIN('ScriptMap') ChapterUrlAccess = MapUrlAccess; ChapterFormat = A['MapFormat']; Cartography = A['Cartography']; if utilities.is_set ( Cartography ) then Cartography = sepc .. " " .. wrap_msg ('cartography', Cartography, use_lowercase); end Scale = A['Scale']; if utilities.is_set ( Scale ) then Scale = sepc .. " " .. Scale; end end -- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data. local Series = A['Series']; if 'episode' == config.CitationClass or 'serial' == config.CitationClass then local SeriesLink = A['SeriesLink']; SeriesLink = link_title_ok (SeriesLink, A:ORIGIN ('SeriesLink'), Series, 'series'); -- check for wiki-markup in |series-link= or wiki-markup in |series= when |series-link= is set local Network = A['Network']; local Station = A['Station']; local s, n = {}, {}; -- do common parameters first if utilities.is_set (Network) then table.insert(n, Network); end if utilities.is_set (Station) then table.insert(n, Station); end ID = table.concat(n, sepc .. ' '); if 'episode' == config.CitationClass then -- handle the oddities that are strictly {{cite episode}} local Season = A['Season']; local SeriesNumber = A['SeriesNumber']; if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then -- these are mutually exclusive so if both are set TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. ' and ' .. utilities.wrap_style ('parameter', 'seriesno')}); -- add error message SeriesNumber = ''; -- unset; prefer |season= over |seriesno= end -- assemble a table of parts concatenated later into Series if utilities.is_set (Season) then table.insert(s, wrap_msg ('season', Season, use_lowercase)); end if utilities.is_set (SeriesNumber) then table.insert(s, wrap_msg ('seriesnum', SeriesNumber, use_lowercase)); end if utilities.is_set (Issue) then table.insert(s, wrap_msg ('episode', Issue, use_lowercase)); end Issue = ''; -- unset because this is not a unique parameter Chapter = Title; -- promote title parameters to chapter ScriptChapter = ScriptTitle; ScriptChapter_origin = A:ORIGIN('ScriptTitle'); ChapterLink = TitleLink; -- alias |episode-link= TransChapter = TransTitle; ChapterURL = URL; ChapterUrlAccess = UrlAccess; ChapterURL_origin = URL_origin; ChapterFormat = Format; Title = Series; -- promote series to title TitleLink = SeriesLink; Series = table.concat(s, sepc .. ' '); -- this is concatenation of season, seriesno, episode number if utilities.is_set (ChapterLink) and not utilities.is_set (ChapterURL) then -- link but not URL Chapter = utilities.make_wikilink (ChapterLink, Chapter); elseif utilities.is_set (ChapterLink) and utilities.is_set (ChapterURL) then -- if both are set, URL links episode; Series = utilities.make_wikilink (ChapterLink, Series); end URL = ''; -- unset TransTitle = ''; ScriptTitle = ''; Format = ''; else -- now oddities that are cite serial Issue = ''; -- unset because this parameter no longer supported by the citation/core version of cite serial Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday? if utilities.is_set (Series) and utilities.is_set (SeriesLink) then Series = utilities.make_wikilink (SeriesLink, Series); end Series = utilities.wrap_style ('italic-title', Series); -- series is italicized end end -- end of {{cite episode}} stuff -- handle type parameter for those CS1 citations that have default values local TitleType = A['TitleType']; local Degree = A['Degree']; if utilities.in_array (config.CitationClass, {'AV-media-notes', 'interview', 'mailinglist', 'map', 'podcast', 'pressrelease', 'report', 'speech', 'techreport', 'thesis'}) then TitleType = set_titletype (config.CitationClass, TitleType); if utilities.is_set (Degree) and "Thesis" == TitleType then -- special case for cite thesis TitleType = Degree .. ' ' .. cfg.title_types ['thesis']:lower(); end end if utilities.is_set (TitleType) then -- if type parameter is specified TitleType = utilities.substitute ( cfg.messages['type'], TitleType); -- display it in parentheses -- TODO: Hack on TitleType to fix bunched parentheses problem end -- legacy: promote PublicationDate to Date if neither Date nor Year are set. local Date = A['Date']; local Date_origin; -- to hold the name of parameter promoted to Date; required for date error messaging local PublicationDate = A['PublicationDate']; local Year = A['Year']; if not utilities.is_set (Date) then Date = Year; -- promote Year to Date Year = nil; -- make nil so Year as empty string isn't used for CITEREF if not utilities.is_set (Date) and utilities.is_set (PublicationDate) then -- use PublicationDate when |date= and |year= are not set Date = PublicationDate; -- promote PublicationDate to Date PublicationDate = ''; -- unset, no longer needed Date_origin = A:ORIGIN('PublicationDate'); -- save the name of the promoted parameter else Date_origin = A:ORIGIN('Year'); -- save the name of the promoted parameter end else Date_origin = A:ORIGIN('Date'); -- not a promotion; name required for error messaging end if PublicationDate == Date then PublicationDate = ''; end -- if PublicationDate is same as Date, don't display in rendered citation --[[ Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where we get the date used in the metadata. Date validation supporting code is in Module:Citation/CS1/Date_validation ]] local DF = is_valid_parameter_value (A['DF'], A:ORIGIN('DF'), cfg.keywords_lists['df'], ''); if not utilities.is_set (DF) then DF = cfg.global_df; -- local |df= if present overrides global df set by {{use xxx date}} template end local ArchiveURL; local ArchiveDate; local ArchiveFormat = A['ArchiveFormat']; ArchiveURL, ArchiveDate = archive_url_check (A['ArchiveURL'], A['ArchiveDate']) ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, 'archive-format', 'archive-url'); ArchiveURL, ArchiveDate = is_unique_archive_url (ArchiveURL, URL, ChapterURL, A:ORIGIN('ArchiveURL'), ArchiveDate); -- add error message when URL or ChapterURL == ArchiveURL local AccessDate = A['AccessDate']; local LayDate = A['LayDate']; local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification local DoiBroken = A['DoiBroken']; local Embargo = A['Embargo']; local anchor_year; -- used in the CITEREF identifier do -- create defined block to contain local variables error_message, date_parameters_list, mismatch local error_message = ''; -- AirDate has been promoted to Date so not necessary to check it local date_parameters_list = { ['access-date'] = {val = AccessDate, name = A:ORIGIN ('AccessDate')}, ['archive-date'] = {val = ArchiveDate, name = A:ORIGIN ('ArchiveDate')}, ['date'] = {val = Date, name = Date_origin}, ['doi-broken-date'] = {val = DoiBroken, name = A:ORIGIN ('DoiBroken')}, ['pmc-embargo-date'] = {val = Embargo, name = A:ORIGIN ('Embargo')}, ['lay-date'] = {val = LayDate, name = A:ORIGIN ('LayDate')}, ['publication-date'] = {val = PublicationDate, name = A:ORIGIN ('PublicationDate')}, ['year'] = {val = Year, name = A:ORIGIN ('Year')}, }; local error_list = {}; anchor_year, Embargo = validation.dates(date_parameters_list, COinS_date, error_list); -- start temporary Julian / Gregorian calendar uncertainty categorization if COinS_date.inter_cal_cat then utilities.add_prop_cat ('jul-greg-uncertainty'); end -- end temporary Julian / Gregorian calendar uncertainty categorization if utilities.is_set (Year) and utilities.is_set (Date) then -- both |date= and |year= not normally needed; validation.year_date_check (Year, A:ORIGIN ('Year'), Date, A:ORIGIN ('Date'), error_list); end if 0 == #error_list then -- error free dates only; 0 when error_list is empty local modified = false; -- flag if utilities.is_set (DF) then -- if we need to reformat dates modified = validation.reformat_dates (date_parameters_list, DF); -- reformat to DF format, use long month names if appropriate end if true == validation.date_hyphen_to_dash (date_parameters_list) then -- convert hyphens to dashes where appropriate modified = true; utilities.set_message ('maint_date_format'); -- hyphens were converted so add maint category end -- for those wikis that can and want to have English date names translated to the local language; not supported at en.wiki if cfg.date_name_auto_xlate_enable and validation.date_name_xlate (date_parameters_list, cfg.date_digit_auto_xlate_enable ) then utilities.set_message ('maint_date_auto_xlated'); -- add maint cat modified = true; end if modified then -- if the date_parameters_list values were modified AccessDate = date_parameters_list['access-date'].val; -- overwrite date holding parameters with modified values ArchiveDate = date_parameters_list['archive-date'].val; Date = date_parameters_list['date'].val; DoiBroken = date_parameters_list['doi-broken-date'].val; LayDate = date_parameters_list['lay-date'].val; PublicationDate = date_parameters_list['publication-date'].val; end else utilities.set_message ('err_bad_date', {utilities.make_sep_list (#error_list, error_list)}); -- add this error message end end -- end of do local ID_list = {}; -- sequence table of rendered identifiers local ID_list_coins = {}; -- table of identifiers and their values from args; key is same as cfg.id_handlers's key local Class = A['Class']; -- arxiv class identifier local ID_support = { {A['ASINTLD'], 'ASIN', 'err_asintld_missing_asin', A:ORIGIN ('ASINTLD')}, {DoiBroken, 'DOI', 'err_doibroken_missing_doi', A:ORIGIN ('DoiBroken')}, {Embargo, 'PMC', 'err_embargo_missing_pmc', A:ORIGIN ('Embargo')}, } ID_list, ID_list_coins = identifiers.identifier_lists_get (args, {DoiBroken = DoiBroken, ASINTLD = A['ASINTLD'], Embargo = Embargo, Class = Class}, ID_support); -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data. if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then if not utilities.is_set (ID_list_coins[config.CitationClass:upper()]) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv= & |citeseerx= required for their templates utilities.set_message ('err_' .. config.CitationClass .. '_missing'); -- add error message end Periodical = ({['arxiv'] = 'arXiv', ['biorxiv'] = 'bioRxiv', ['citeseerx'] = 'CiteSeerX', ['ssrn'] = 'Social Science Research Network'})[config.CitationClass]; end -- Link the title of the work if no |url= was provided, but we have a |pmc= or a |doi= with |doi-access=free if config.CitationClass == "journal" and not utilities.is_set (URL) and not utilities.is_set (TitleLink) and not utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) then -- TODO: remove 'none' once existing citations have been switched to 'off', so 'none' can be used as token for "no title" instead if 'none' ~= cfg.keywords_xlate[auto_select] then -- if auto-linking not disabled if identifiers.auto_link_urls[auto_select] then -- manual selection URL = identifiers.auto_link_urls[auto_select]; -- set URL to be the same as identifier's external link URL_origin = cfg.id_handlers[auto_select:upper()].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title= elseif identifiers.auto_link_urls['pmc'] then -- auto-select PMC URL = identifiers.auto_link_urls['pmc']; -- set URL to be the same as the PMC external link if not embargoed URL_origin = cfg.id_handlers['PMC'].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title= elseif identifiers.auto_link_urls['doi'] then -- auto-select DOI URL = identifiers.auto_link_urls['doi']; URL_origin = cfg.id_handlers['DOI'].parameters[1]; end end if utilities.is_set (URL) then -- set when using an identifier-created URL if utilities.is_set (AccessDate) then -- |access-date= requires |url=; identifier-created URL is not |url= utilities.set_message ('err_accessdate_missing_url'); -- add an error message AccessDate = ''; -- unset end if utilities.is_set (ArchiveURL) then -- |archive-url= requires |url=; identifier-created URL is not |url= utilities.set_message ('err_archive_missing_url'); -- add an error message ArchiveURL = ''; -- unset end end end -- At this point fields may be nil if they weren't specified in the template use. We can use that fact. -- Test if citation has no title if not utilities.is_set (Title) and not utilities.is_set (TransTitle) and not utilities.is_set (ScriptTitle) then -- has special case for cite episode utilities.set_message ('err_citation_missing_title', {'episode' == config.CitationClass and 'series' or 'title'}); end if utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) and utilities.in_array (config.CitationClass, {'journal', 'citation'}) and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and ('journal' == Periodical_origin or 'script-journal' == ScriptPeriodical_origin) then -- special case for journal cites Title = ''; -- set title to empty string utilities.set_message ('maint_untitled'); -- add maint cat end -- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information. -- handle the oddity that is cite encyclopedia and {{citation |encyclopedia=something}}. Here we presume that -- when Periodical, Title, and Chapter are all set, then Periodical is the book (encyclopedia) title, Title -- is the article title, and Chapter is a section within the article. So, we remap local coins_chapter = Chapter; -- default assuming that remapping not required local coins_title = Title; -- et tu if 'encyclopaedia' == config.CitationClass or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then if utilities.is_set (Chapter) and utilities.is_set (Title) and utilities.is_set (Periodical) then -- if all are used then coins_chapter = Title; -- remap coins_title = Periodical; end end local coins_author = a; -- default for coins rft.au if 0 < #c then -- but if contributor list coins_author = c; -- use that instead end local QuotePage = A['QuotePage']; local QuotePages = utilities.hyphen_to_dash (A['QuotePages']); -- this is the function call to COinS() local OCinSoutput = metadata.COinS({ ['Periodical'] = utilities.strip_apostrophe_markup (Periodical), -- no markup in the metadata ['Encyclopedia'] = Encyclopedia, -- just a flag; content ignored by ~/COinS ['Chapter'] = metadata.make_coins_title (coins_chapter, ScriptChapter), -- Chapter and ScriptChapter stripped of bold / italic / accept-as-written markup ['Degree'] = Degree; -- cite thesis only ['Title'] = metadata.make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic / accept-as-written markup ['PublicationPlace'] = PublicationPlace, ['Date'] = COinS_date.rftdate, -- COinS_date has correctly formatted date if Date is valid; ['Season'] = COinS_date.rftssn, ['Quarter'] = COinS_date.rftquarter, ['Chron'] = COinS_date.rftchron or (not COinS_date.rftdate and Date) or '', -- chron but if not set and invalid date format use Date; keep this last bit? ['Series'] = Series, ['Volume'] = Volume, ['Issue'] = Issue, ['Pages'] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)), -- pages stripped of external links ['Edition'] = Edition, ['PublisherName'] = PublisherName or Newsgroup, -- any apostrophe markup already removed from PublisherName ['URL'] = first_set ({ChapterURL, URL}, 2), ['Authors'] = coins_author, ['ID_list'] = ID_list_coins, ['RawPage'] = this_page.prefixedText, }, config.CitationClass); -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, and {{cite ssrn}} AFTER generation of COinS data. if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then -- we have set rft.jtitle in COinS to arXiv, bioRxiv, CiteSeerX, or ssrn now unset so it isn't displayed Periodical = ''; -- periodical not allowed in these templates; if article has been published, use cite journal end -- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text if 'newsgroup' == config.CitationClass and utilities.is_set (Newsgroup) then PublisherName = utilities.substitute (cfg.messages['newsgroup'], external_link( 'news:' .. Newsgroup, Newsgroup, Newsgroup_origin, nil )); end local Editors; local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list local Contributors; -- assembled contributors name list local contributor_etal; local Translators; -- assembled translators name list local translator_etal; local t = {}; -- translators list from |translator-lastn= / translator-firstn= pairs t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn= local Interviewers; local interviewers_list = {}; interviewers_list = extract_names (args, 'InterviewerList'); -- process preferred interviewers parameters local interviewer_etal; -- Now perform various field substitutions. -- We also add leading spaces and surrounding markup and punctuation to the -- various parts of the citation, but only when they are non-nil. do local last_first_list; local control = { format = NameListStyle, -- empty string or 'vanc' maximum = nil, -- as if display-authors or display-editors not set mode = Mode }; do -- do editor name list first because the now unsupported coauthors used to modify control table control.maximum , editor_etal = get_display_names (A['DisplayEditors'], #e, 'editors', editor_etal, A:ORIGIN ('DisplayEditors')); Editors, EditorCount = list_people (control, e, editor_etal); if 1 == EditorCount and (true == editor_etal or 1 < #e) then -- only one editor displayed but includes etal then EditorCount = 2; -- spoof to display (eds.) annotation end end do -- now do interviewers control.maximum, interviewer_etal = get_display_names (A['DisplayInterviewers'], #interviewers_list, 'interviewers', interviewer_etal, A:ORIGIN ('DisplayInterviewers')); Interviewers = list_people (control, interviewers_list, interviewer_etal); end do -- now do translators control.maximum, translator_etal = get_display_names (A['DisplayTranslators'], #t, 'translators', translator_etal, A:ORIGIN ('DisplayTranslators')); Translators = list_people (control, t, translator_etal); end do -- now do contributors control.maximum, contributor_etal = get_display_names (A['DisplayContributors'], #c, 'contributors', contributor_etal, A:ORIGIN ('DisplayContributors')); Contributors = list_people (control, c, contributor_etal); end do -- now do authors control.maximum, author_etal = get_display_names (A['DisplayAuthors'], #a, 'authors', author_etal, A:ORIGIN ('DisplayAuthors')); last_first_list = list_people (control, a, author_etal); if utilities.is_set (Authors) then Authors, author_etal = name_has_etal (Authors, author_etal, false, 'authors'); -- find and remove variations on et al. if author_etal then Authors = Authors .. ' ' .. cfg.messages['et al']; -- add et al. to authors parameter end else Authors = last_first_list; -- either an author name list or an empty string end end -- end of do if utilities.is_set (Authors) and utilities.is_set (Collaboration) then Authors = Authors .. ' (' .. Collaboration .. ')'; -- add collaboration after et al. end end local ConferenceFormat = A['ConferenceFormat']; local ConferenceURL = A['ConferenceURL']; ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, 'conference-format', 'conference-url'); Format = style_format (Format, URL, 'format', 'url'); -- special case for chapter format so no error message or cat when chapter not supported if not (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia))) then ChapterFormat = style_format (ChapterFormat, ChapterURL, 'chapter-format', 'chapter-url'); end if not utilities.is_set (URL) then if utilities.in_array (config.CitationClass, {"web", "podcast", "mailinglist"}) or -- |url= required for cite web, cite podcast, and cite mailinglist ('citation' == config.CitationClass and ('website' == Periodical_origin or 'script-website' == ScriptPeriodical_origin)) then -- and required for {{citation}} with |website= or |script-website= utilities.set_message ('err_cite_web_url'); end -- do we have |accessdate= without either |url= or |chapter-url=? if utilities.is_set (AccessDate) and not utilities.is_set (ChapterURL) then -- ChapterURL may be set when URL is not set; utilities.set_message ('err_accessdate_missing_url'); AccessDate = ''; end end local UrlStatus = is_valid_parameter_value (A['UrlStatus'], A:ORIGIN('UrlStatus'), cfg.keywords_lists['url-status'], ''); local OriginalURL local OriginalURL_origin local OriginalFormat local OriginalAccess; UrlStatus = UrlStatus:lower(); -- used later when assembling archived text if utilities.is_set ( ArchiveURL ) then if utilities.is_set (ChapterURL) then -- if chapter-url= is set apply archive url to it OriginalURL = ChapterURL; -- save copy of source chapter's url for archive text OriginalURL_origin = ChapterURL_origin; -- name of |chapter-url= parameter for error messages OriginalFormat = ChapterFormat; -- and original |chapter-format= if 'live' ~= UrlStatus then ChapterURL = ArchiveURL -- swap-in the archive's URL ChapterURL_origin = A:ORIGIN('ArchiveURL') -- name of |archive-url= parameter for error messages ChapterFormat = ArchiveFormat or ''; -- swap in archive's format ChapterUrlAccess = nil; -- restricted access levels do not make sense for archived URLs end elseif utilities.is_set (URL) then OriginalURL = URL; -- save copy of original source URL OriginalURL_origin = URL_origin; -- name of URL parameter for error messages OriginalFormat = Format; -- and original |format= OriginalAccess = UrlAccess; if 'live' ~= UrlStatus then -- if URL set then |archive-url= applies to it URL = ArchiveURL -- swap-in the archive's URL URL_origin = A:ORIGIN('ArchiveURL') -- name of archive URL parameter for error messages Format = ArchiveFormat or ''; -- swap in archive's format UrlAccess = nil; -- restricted access levels do not make sense for archived URLs end end elseif utilities.is_set (UrlStatus) then -- if |url-status= is set when |archive-url= is not set utilities.set_message ('maint_url_status'); -- add maint cat end if utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or -- if any of the 'periodical' cites except encyclopedia ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) then local chap_param; if utilities.is_set (Chapter) then -- get a parameter name from one of these chapter related meta-parameters chap_param = A:ORIGIN ('Chapter') elseif utilities.is_set (TransChapter) then chap_param = A:ORIGIN ('TransChapter') elseif utilities.is_set (ChapterURL) then chap_param = A:ORIGIN ('ChapterURL') elseif utilities.is_set (ScriptChapter) then chap_param = ScriptChapter_origin; else utilities.is_set (ChapterFormat) chap_param = A:ORIGIN ('ChapterFormat') end if utilities.is_set (chap_param) then -- if we found one utilities.set_message ('err_chapter_ignored', {chap_param}); -- add error message Chapter = ''; -- and set them to empty string to be safe with concatenation TransChapter = ''; ChapterURL = ''; ScriptChapter = ''; ChapterFormat = ''; end else -- otherwise, format chapter / article title local no_quotes = false; -- default assume that we will be quoting the chapter parameter value if utilities.is_set (Contribution) and 0 < #c then -- if this is a contribution with contributor(s) if utilities.in_array (Contribution:lower(), cfg.keywords_lists.contribution) then -- and a generic contribution title no_quotes = true; -- then render it unquoted end end Chapter = format_chapter_title (ScriptChapter, ScriptChapter_origin, Chapter, Chapter_origin, TransChapter, TransChapter_origin, ChapterURL, ChapterURL_origin, no_quotes, ChapterUrlAccess); -- Contribution is also in Chapter if utilities.is_set (Chapter) then Chapter = Chapter .. ChapterFormat ; if 'map' == config.CitationClass and utilities.is_set (TitleType) then Chapter = Chapter .. ' ' .. TitleType; -- map annotation here; not after title end Chapter = Chapter .. sepc .. ' '; elseif utilities.is_set (ChapterFormat) then -- |chapter= not set but |chapter-format= is so ... Chapter = ChapterFormat .. sepc .. ' '; -- ... ChapterFormat has error message, we want to see it end end -- Format main title local plain_title = false; local accept_title; Title, accept_title = utilities.has_accept_as_written (Title, true); -- remove accept-this-as-written markup when it wraps all of <Title> if accept_title and ('' == Title) then -- only support forced empty for now "(())" Title = cfg.messages['notitle']; -- replace by predefined "No title" message -- TODO: utilities.set_message ( 'err_redundant_parameters', ...); -- issue proper error message instead of muting ScriptTitle = ''; -- just mute for now TransTitle = ''; -- just mute for now plain_title = true; -- suppress text decoration for descriptive title utilities.set_message ('maint_untitled'); -- add maint cat end if not accept_title then -- <Title> not wrapped in accept-as-written markup if '...' == Title:sub (-3) then -- if ellipsis is the last three characters of |title= Title = Title:gsub ('(%.%.%.)%.+$', '%1'); -- limit the number of dots to three elseif not mw.ustring.find (Title, '%.%s*%a%.$') and -- end of title is not a 'dot-(optional space-)letter-dot' initialism ... not mw.ustring.find (Title, '%s+%a%.$') then -- ...and not a 'space-letter-dot' initial (''Allium canadense'' L.) Title = mw.ustring.gsub(Title, '%' .. sepc .. '$', ''); -- remove any trailing separator character; sepc and ms.ustring() here for languages that use multibyte separator characters end if utilities.is_set (ArchiveURL) and is_archived_copy (Title) then utilities.set_message ('maint_archived_copy'); -- add maintenance category before we modify the content of Title end if is_generic ('generic_titles', Title) then utilities.set_message ('err_generic_title'); -- set an error message end end if (not plain_title) and (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) or ('map' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)))) then -- special case for cite map when the map is in a periodical treat as an article Title = kern_quotes (Title); -- if necessary, separate title's leading and trailing quote marks from module provided quote marks Title = utilities.wrap_style ('quoted-title', Title); Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); elseif plain_title or ('report' == config.CitationClass) then -- no styling for cite report and descriptive titles (otherwise same as above) Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); -- for cite report, use this form for trans-title else Title = utilities.wrap_style ('italic-title', Title); Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped TransTitle = utilities.wrap_style ('trans-italic-title', TransTitle); end if utilities.is_set (TransTitle) then if utilities.is_set (Title) then TransTitle = " " .. TransTitle; else utilities.set_message ('err_trans_missing_title', {'title'}); end end if utilities.is_set (Title) then -- TODO: is this the right place to be making Wikisource URLs? if utilities.is_set (TitleLink) and utilities.is_set (URL) then utilities.set_message ('err_wikilink_in_url'); -- set an error message because we can't have both TitleLink = ''; -- unset end if not utilities.is_set (TitleLink) and utilities.is_set (URL) then Title = external_link (URL, Title, URL_origin, UrlAccess) .. TransTitle .. Format; URL = ''; -- unset these because no longer needed Format = ""; elseif utilities.is_set (TitleLink) and not utilities.is_set (URL) then local ws_url; ws_url = wikisource_url_make (TitleLink); -- ignore ws_label return; not used here if ws_url then Title = external_link (ws_url, Title .. '&nbsp;', 'ws link in title-link'); -- space char after Title to move icon away from italic text; TODO: a better way to do this? Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], TitleLink, Title}); Title = Title .. TransTitle; else Title = utilities.make_wikilink (TitleLink, Title) .. TransTitle; end else local ws_url, ws_label, L; -- Title has italic or quote markup by the time we get here which causes is_wikilink() to return 0 (not a wikilink) ws_url, ws_label, L = wikisource_url_make (Title:gsub('^[\'"]*(.-)[\'"]*$', '%1')); -- make ws URL from |title= interwiki link (strip italic or quote markup); link portion L becomes tooltip label if ws_url then Title = Title:gsub ('%b[]', ws_label); -- replace interwiki link with ws_label to retain markup Title = external_link (ws_url, Title .. '&nbsp;', 'ws link in title'); -- space char after Title to move icon away from italic text; TODO: a better way to do this? Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, Title}); Title = Title .. TransTitle; else Title = Title .. TransTitle; end end else Title = TransTitle; end if utilities.is_set (Place) then Place = " " .. wrap_msg ('written', Place, use_lowercase) .. sepc .. " "; end local ConferenceURL_origin = A:ORIGIN('ConferenceURL'); -- get name of parameter that holds ConferenceURL if utilities.is_set (Conference) then if utilities.is_set (ConferenceURL) then Conference = external_link( ConferenceURL, Conference, ConferenceURL_origin, nil ); end Conference = sepc .. " " .. Conference .. ConferenceFormat; elseif utilities.is_set (ConferenceURL) then Conference = sepc .. " " .. external_link( ConferenceURL, nil, ConferenceURL_origin, nil ); end local Position = ''; if not utilities.is_set (Position) then local Minutes = A['Minutes']; local Time = A['Time']; if utilities.is_set (Minutes) then if utilities.is_set (Time) then --TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. ' and ' .. utilities.wrap_style ('parameter', 'time')}); end Position = " " .. Minutes .. " " .. cfg.messages['minutes']; else if utilities.is_set (Time) then local TimeCaption = A['TimeCaption'] if not utilities.is_set (TimeCaption) then TimeCaption = cfg.messages['event']; if sepc ~= '.' then TimeCaption = TimeCaption:lower(); end end Position = " " .. TimeCaption .. " " .. Time; end end else Position = " " .. Position; At = ''; end Page, Pages, Sheet, Sheets = format_pages_sheets (Page, Pages, Sheet, Sheets, config.CitationClass, Periodical_origin, sepc, NoPP, use_lowercase); At = utilities.is_set (At) and (sepc .. " " .. At) or ""; Position = utilities.is_set (Position) and (sepc .. " " .. Position) or ""; if config.CitationClass == 'map' then local Sections = A['Sections']; -- Section (singular) is an alias of Chapter so set earlier local Inset = A['Inset']; if utilities.is_set ( Inset ) then Inset = sepc .. " " .. wrap_msg ('inset', Inset, use_lowercase); end if utilities.is_set ( Sections ) then Section = sepc .. " " .. wrap_msg ('sections', Sections, use_lowercase); elseif utilities.is_set ( Section ) then Section = sepc .. " " .. wrap_msg ('section', Section, use_lowercase); end At = At .. Inset .. Section; end local Others = A['Others']; if utilities.is_set (Others) and 0 == #a and 0 == #e then -- add maint cat when |others= has value and used without |author=, |editor= if config.CitationClass == "AV-media-notes" or config.CitationClass == "audio-visual" then -- special maint for AV/M which has a lot of 'false' positives right now utilities.set_message ('maint_others_avm') else utilities.set_message ('maint_others'); end end Others = utilities.is_set (Others) and (sepc .. " " .. Others) or ""; if utilities.is_set (Translators) then Others = safe_join ({sepc .. ' ', wrap_msg ('translated', Translators, use_lowercase), Others}, sepc); end if utilities.is_set (Interviewers) then Others = safe_join ({sepc .. ' ', wrap_msg ('interview', Interviewers, use_lowercase), Others}, sepc); end local TitleNote = A['TitleNote']; TitleNote = utilities.is_set (TitleNote) and (sepc .. " " .. TitleNote) or ""; if utilities.is_set (Edition) then if Edition:match ('%f[%a][Ee]d%n?%.?$') or Edition:match ('%f[%a][Ee]dition$') then -- Ed, ed, Ed., ed., Edn, edn, Edn., edn. utilities.set_message ('err_extra_text_edition'); -- add error message end Edition = " " .. wrap_msg ('edition', Edition); else Edition = ''; end Series = utilities.is_set (Series) and wrap_msg ('series', {sepc, Series}) or ""; -- not the same as SeriesNum local Agency = A['Agency']; Agency = utilities.is_set (Agency) and wrap_msg ('agency', {sepc, Agency}) or ""; Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase); if utilities.is_set (AccessDate) then local retrv_text = " " .. cfg.messages['retrieved'] AccessDate = nowrap_date (AccessDate); -- wrap in nowrap span if date in appropriate format if (sepc ~= ".") then retrv_text = retrv_text:lower() end -- if mode is cs2, lower case AccessDate = utilities.substitute (retrv_text, AccessDate); -- add retrieved text AccessDate = utilities.substitute (cfg.presentation['accessdate'], {sepc, AccessDate}); -- allow editors to hide accessdates end if utilities.is_set (ID) then ID = sepc .. " " .. ID; end local Docket = A['Docket']; if "thesis" == config.CitationClass and utilities.is_set (Docket) then ID = sepc .. " Docket " .. Docket .. ID; end if "report" == config.CitationClass and utilities.is_set (Docket) then -- for cite report when |docket= is set ID = sepc .. ' ' .. Docket; -- overwrite ID even if |id= is set end if utilities.is_set (URL) then URL = " " .. external_link( URL, nil, URL_origin, UrlAccess ); end local Quote = A['Quote']; local TransQuote = A['TransQuote']; local ScriptQuote = A['ScriptQuote']; if utilities.is_set (Quote) or utilities.is_set (TransQuote) or utilities.is_set (ScriptQuote) then if utilities.is_set (Quote) then if Quote:sub(1, 1) == '"' and Quote:sub(-1, -1) == '"' then -- if first and last characters of quote are quote marks Quote = Quote:sub(2, -2); -- strip them off end end Quote = utilities.wrap_style ('quoted-text', Quote ); -- wrap in <q>...</q> tags if utilities.is_set (ScriptQuote) then Quote = script_concatenate (Quote, ScriptQuote, 'script-quote'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after quote is wrapped end if utilities.is_set (TransQuote) then if TransQuote:sub(1, 1) == '"' and TransQuote:sub(-1, -1) == '"' then -- if first and last characters of |trans-quote are quote marks TransQuote = TransQuote:sub(2, -2); -- strip them off end Quote = Quote .. " " .. utilities.wrap_style ('trans-quoted-title', TransQuote ); end if utilities.is_set (QuotePage) or utilities.is_set (QuotePages) then -- add page prefix local quote_prefix = ''; if utilities.is_set (QuotePage) then extra_text_in_page_check (QuotePage, 'quote-page'); -- add to maint cat if |quote-page= value begins with what looks like p., pp., etc. if not NoPP then quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, QuotePage}), '', '', ''; else quote_prefix = utilities.substitute (cfg.messages['nopp'], {sepc, QuotePage}), '', '', ''; end elseif utilities.is_set (QuotePages) then extra_text_in_page_check (QuotePages, 'quote-pages'); -- add to maint cat if |quote-pages= value begins with what looks like p., pp., etc. if tonumber(QuotePages) ~= nil and not NoPP then -- if only digits, assume single page quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, QuotePages}), '', ''; elseif not NoPP then quote_prefix = utilities.substitute (cfg.messages['pp-prefix'], {sepc, QuotePages}), '', ''; else quote_prefix = utilities.substitute (cfg.messages['nopp'], {sepc, QuotePages}), '', ''; end end Quote = quote_prefix .. ": " .. Quote; else Quote = sepc .. " " .. Quote; end PostScript = ""; -- cs1|2 does not supply terminal punctuation when |quote= is set end -- We check length of PostScript here because it will have been nuked by -- the quote parameters. We'd otherwise emit a message even if there wasn't -- a displayed postscript. -- TODO: Should the max size (1) be configurable? -- TODO: Should we check a specific pattern? if utilities.is_set(PostScript) and mw.ustring.len(PostScript) > 1 then utilities.set_message ('maint_postscript') end local Archived; if utilities.is_set (ArchiveURL) then local arch_text; if not utilities.is_set (ArchiveDate) then utilities.set_message ('err_archive_missing_date'); ArchiveDate = ''; -- empty string for concatenation end if "live" == UrlStatus then arch_text = cfg.messages['archived']; if sepc ~= "." then arch_text = arch_text:lower() end if utilities.is_set (ArchiveDate) then Archived = sepc .. ' ' .. utilities.substitute ( cfg.messages['archived-live'], {external_link( ArchiveURL, arch_text, A:ORIGIN('ArchiveURL'), nil) .. ArchiveFormat, ArchiveDate } ); else Archived = ''; end if not utilities.is_set (OriginalURL) then utilities.set_message ('err_archive_missing_url'); Archived = ''; -- empty string for concatenation end elseif utilities.is_set (OriginalURL) then -- UrlStatus is empty, 'dead', 'unfit', 'usurped', 'bot: unknown' if utilities.in_array (UrlStatus, {'unfit', 'usurped', 'bot: unknown'}) then arch_text = cfg.messages['archived-unfit']; if sepc ~= "." then arch_text = arch_text:lower() end Archived = sepc .. ' ' .. arch_text .. ArchiveDate; -- format already styled if 'bot: unknown' == UrlStatus then utilities.set_message ('maint_bot_unknown'); -- and add a category if not already added else utilities.set_message ('maint_unfit'); -- and add a category if not already added end else -- UrlStatus is empty, 'dead' arch_text = cfg.messages['archived-dead']; if sepc ~= "." then arch_text = arch_text:lower() end if utilities.is_set (ArchiveDate) then Archived = sepc .. " " .. utilities.substitute ( arch_text, { external_link( OriginalURL, cfg.messages['original'], OriginalURL_origin, OriginalAccess ) .. OriginalFormat, ArchiveDate } ); -- format already styled else Archived = ''; -- unset for concatenation end end else -- OriginalUrl not set arch_text = cfg.messages['archived-missing']; if sepc ~= "." then arch_text = arch_text:lower() end utilities.set_message ('err_archive_missing_url'); Archived = ''; -- empty string for concatenation end elseif utilities.is_set (ArchiveFormat) then Archived = ArchiveFormat; -- if set and ArchiveURL not set ArchiveFormat has error message else Archived = ''; end local Lay = ''; local LaySource = A['LaySource']; local LayURL = A['LayURL']; local LayFormat = A['LayFormat']; LayFormat = style_format (LayFormat, LayURL, 'lay-format', 'lay-url'); if utilities.is_set (LayURL) then if utilities.is_set (LayDate) then LayDate = " (" .. LayDate .. ")" end if utilities.is_set (LaySource) then LaySource = " &ndash; ''" .. utilities.safe_for_italics (LaySource) .. "''"; else LaySource = ""; end if sepc == '.' then Lay = sepc .. " " .. external_link( LayURL, cfg.messages['lay summary'], A:ORIGIN('LayURL'), nil ) .. LayFormat .. LaySource .. LayDate else Lay = sepc .. " " .. external_link( LayURL, cfg.messages['lay summary']:lower(), A:ORIGIN('LayURL'), nil ) .. LayFormat .. LaySource .. LayDate end elseif utilities.is_set (LayFormat) then -- Test if |lay-format= is given without giving a |lay-url= Lay = sepc .. LayFormat; -- if set and LayURL not set, then LayFormat has error message end local TranscriptURL = A['TranscriptURL'] local TranscriptFormat = A['TranscriptFormat']; TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, 'transcript-format', 'transcripturl'); local Transcript = A['Transcript']; local TranscriptURL_origin = A:ORIGIN('TranscriptURL'); -- get name of parameter that holds TranscriptURL if utilities.is_set (Transcript) then if utilities.is_set (TranscriptURL) then Transcript = external_link( TranscriptURL, Transcript, TranscriptURL_origin, nil ); end Transcript = sepc .. ' ' .. Transcript .. TranscriptFormat; elseif utilities.is_set (TranscriptURL) then Transcript = external_link( TranscriptURL, nil, TranscriptURL_origin, nil ); end local Publisher; if utilities.is_set (PublicationDate) then PublicationDate = wrap_msg ('published', PublicationDate); end if utilities.is_set (PublisherName) then if utilities.is_set (PublicationPlace) then Publisher = sepc .. " " .. PublicationPlace .. ": " .. PublisherName .. PublicationDate; else Publisher = sepc .. " " .. PublisherName .. PublicationDate; end elseif utilities.is_set (PublicationPlace) then Publisher= sepc .. " " .. PublicationPlace .. PublicationDate; else Publisher = PublicationDate; end local TransPeriodical = A['TransPeriodical']; local TransPeriodical_origin = A:ORIGIN ('TransPeriodical'); -- Several of the above rely upon detecting this as nil, so do it last. if (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical)) then if utilities.is_set (Title) or utilities.is_set (TitleNote) then Periodical = sepc .. " " .. format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin); else Periodical = format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin); end end local Language = A['Language']; if utilities.is_set (Language) then Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc. else Language=''; -- language not specified so make sure this is an empty string; --[[ TODO: need to extract the wrap_msg from language_parameter so that we can solve parentheses bunching problem with Format/Language/TitleType ]] end --[[ Handle the oddity that is cite speech. This code overrides whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided). ]] if "speech" == config.CitationClass then -- cite speech only TitleNote = TitleType; -- move TitleType to TitleNote so that it renders ahead of |event= TitleType = ''; -- and unset if utilities.is_set (Periodical) then -- if Periodical, perhaps because of an included |website= or |journal= parameter if utilities.is_set (Conference) then -- and if |event= is set Conference = Conference .. sepc .. " "; -- then add appropriate punctuation to the end of the Conference variable before rendering end end end -- Piece all bits together at last. Here, all should be non-nil. -- We build things this way because it is more efficient in LUA -- not to keep reassigning to the same string variable over and over. local tcommon; local tcommon2; -- used for book cite when |contributor= is set if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then if utilities.is_set (Others) then Others = safe_join ({Others, sepc .. " "}, sepc) end -- add terminal punctuation & space; check for dup sepc; TODO why do we need to do this here? tcommon = safe_join( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Edition, Publisher, Agency, Volume}, sepc ); elseif utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (Periodical) then -- special cases for book cites if utilities.is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc. tcommon = safe_join( {Title, TitleNote}, sepc ); -- author and other stuff will come after this and before tcommon2 tcommon2 = safe_join( {Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); else tcommon = safe_join( {Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); end elseif 'map' == config.CitationClass then -- special cases for cite map if utilities.is_set (Chapter) then -- map in a book; TitleType is part of Chapter tcommon = safe_join( {Title, Format, Edition, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc ); elseif utilities.is_set (Periodical) then -- map in a periodical tcommon = safe_join( {Title, TitleType, Format, Periodical, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc ); else -- a sheet or stand-alone map tcommon = safe_join( {Title, TitleType, Format, Edition, Scale, Series, Language, Cartography, Others, Publisher}, sepc ); end elseif 'episode' == config.CitationClass then -- special case for cite episode tcommon = safe_join( {Title, TitleNote, TitleType, Series, Language, Edition, Publisher}, sepc ); else -- all other CS1 templates tcommon = safe_join( {Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); end if #ID_list > 0 then ID_list = safe_join( { sepc .. " ", table.concat( ID_list, sepc .. " " ), ID }, sepc ); else ID_list = ID; end local Via = A['Via']; Via = utilities.is_set (Via) and wrap_msg ('via', Via) or ''; local idcommon; if 'audio-visual' == config.CitationClass or 'episode' == config.CitationClass then -- special case for cite AV media & cite episode position transcript idcommon = safe_join( { ID_list, URL, Archived, Transcript, AccessDate, Via, Lay, Quote }, sepc ); else idcommon = safe_join( { ID_list, URL, Archived, AccessDate, Via, Lay, Quote }, sepc ); end local text; local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At; local OrigDate = A['OrigDate']; OrigDate = utilities.is_set (OrigDate) and wrap_msg ('origdate', OrigDate) or ''; if utilities.is_set (Date) then if utilities.is_set (Authors) or utilities.is_set (Editors) then -- date follows authors or editors when authors not set Date = " (" .. Date .. ")" .. OrigDate .. sepc .. " "; -- in parentheses else -- neither of authors and editors set if (string.sub(tcommon, -1, -1) == sepc) then -- if the last character of tcommon is sepc Date = " " .. Date .. OrigDate; -- Date does not begin with sepc else Date = sepc .. " " .. Date .. OrigDate; -- Date begins with sepc end end end if utilities.is_set (Authors) then if (not utilities.is_set (Date)) then -- when date is set it's in parentheses; no Authors termination Authors = terminate_name_list (Authors, sepc); -- when no date, terminate with 0 or 1 sepc and a space end if utilities.is_set (Editors) then local in_text = " "; local post_text = ""; if utilities.is_set (Chapter) and 0 == #c then in_text = in_text .. cfg.messages['in'] .. " " if (sepc ~= '.') then in_text = in_text:lower() -- lowercase for cs2 end end if EditorCount <= 1 then post_text = " (" .. cfg.messages['editor'] .. ")"; -- be consistent with no-author, no-date case else post_text = " (" .. cfg.messages['editors'] .. ")"; end Editors = terminate_name_list (in_text .. Editors .. post_text, sepc); -- terminate with 0 or 1 sepc and a space end if utilities.is_set (Contributors) then -- book cite and we're citing the intro, preface, etc. local by_text = sepc .. ' ' .. cfg.messages['by'] .. ' '; if (sepc ~= '.') then by_text = by_text:lower() end -- lowercase for cs2 Authors = by_text .. Authors; -- author follows title so tweak it here if utilities.is_set (Editors) and utilities.is_set (Date) then -- when Editors make sure that Authors gets terminated Authors = terminate_name_list (Authors, sepc); -- terminate with 0 or 1 sepc and a space end if (not utilities.is_set (Date)) then -- when date is set it's in parentheses; no Contributors termination Contributors = terminate_name_list (Contributors, sepc); -- terminate with 0 or 1 sepc and a space end text = safe_join( {Contributors, Date, Chapter, tcommon, Authors, Place, Editors, tcommon2, pgtext, idcommon }, sepc ); else text = safe_join( {Authors, Date, Chapter, Place, Editors, tcommon, pgtext, idcommon }, sepc ); end elseif utilities.is_set (Editors) then if utilities.is_set (Date) then if EditorCount <= 1 then Editors = Editors .. ", " .. cfg.messages['editor']; else Editors = Editors .. ", " .. cfg.messages['editors']; end else if EditorCount <= 1 then Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " " else Editors = Editors .. " (" .. cfg.messages['editors'] .. ")" .. sepc .. " " end end text = safe_join( {Editors, Date, Chapter, Place, tcommon, pgtext, idcommon}, sepc ); else if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then text = safe_join( {Chapter, Place, tcommon, pgtext, Date, idcommon}, sepc ); else text = safe_join( {Chapter, Place, tcommon, Date, pgtext, idcommon}, sepc ); end end if utilities.is_set (PostScript) and PostScript ~= sepc then text = safe_join( {text, sepc}, sepc ); -- Deals with italics, spaces, etc. text = text:sub(1, -sepc:len() - 1); end text = safe_join( {text, PostScript}, sepc ); -- Now enclose the whole thing in a <cite> element local options_t = {}; options_t.class = cite_class_attribute_make (config.CitationClass, Mode); local Ref = is_valid_parameter_value (A['Ref'], A:ORIGIN('Ref'), cfg.keywords_lists['ref'], nil, true); -- nil when |ref=harv; A['Ref'] else if 'none' ~= cfg.keywords_xlate[(Ref and Ref:lower()) or ''] then local namelist_t = {}; -- holds selected contributor, author, editor name list local year = first_set ({Year, anchor_year}, 2); -- Year first for legacy citations and for YMD dates that require disambiguation if #c > 0 then -- if there is a contributor list namelist_t = c; -- select it elseif #a > 0 then -- or an author list namelist_t = a; elseif #e > 0 then -- or an editor list namelist_t = e; end local citeref_id; if #namelist_t > 0 then -- if there are names in namelist_t citeref_id = make_citeref_id (namelist_t, year); -- go make the CITEREF anchor if mw.uri.anchorEncode (citeref_id) == ((Ref and mw.uri.anchorEncode (Ref)) or '') then -- Ref may already be encoded (by {{sfnref}}) so citeref_id must be encoded before comparison utilities.set_message ('maint_ref_duplicates_default'); end else citeref_id = ''; -- unset end options_t.id = Ref or citeref_id; end if string.len (text:gsub('%b<>', '')) <= 2 then -- remove html and html-like tags; then get length of what remains; z.error_cats_t = {}; -- blank the categories list z.error_msgs_t = {}; -- blank the error messages list OCinSoutput = nil; -- blank the metadata string text = ''; -- blank the the citation utilities.set_message ('err_empty_citation'); -- set empty citation message and category end local render_t = {}; -- here we collect the final bits for concatenation into the rendered citation if utilities.is_set (options_t.id) then -- here we wrap the rendered citation in <cite ...>...</cite> tags table.insert (render_t, utilities.substitute (cfg.presentation['cite-id'], {mw.uri.anchorEncode(options_t.id), mw.text.nowiki(options_t.class), text})); -- when |ref= is set or when there is a namelist else table.insert (render_t, utilities.substitute (cfg.presentation['cite'], {mw.text.nowiki(options_t.class), text})); -- when |ref=none or when namelist_t empty and |ref= is missing or is empty end if OCinSoutput then -- blanked when citation is 'empty' so don't bother to add boilerplate metadata span table.insert (render_t, utilities.substitute (cfg.presentation['ocins'], OCinSoutput)); -- format and append metadata to the citation end local template_name = ('citation' == config.CitationClass) and 'citation' or 'cite ' .. (cfg.citation_class_map_t[config.CitationClass] or config.CitationClass); local template_link = '[[Template:' .. template_name .. '|' .. template_name .. ']]'; local msg_prefix = '<code class="cs1-code">{{' .. template_link .. '}}</code>: '; if 0 ~= #z.error_msgs_t then mw.addWarning (utilities.substitute (cfg.messages.warning_msg_e, template_link)); table.insert (render_t, ' '); -- insert a space between citation and its error messages table.sort (z.error_msgs_t); -- sort the error messages list; sorting includes wrapping <span> and <code> tags; hidden-error sorts ahead of visible-error local hidden = true; -- presume that the only error messages emited by this template are hidden for _, v in ipairs (z.error_msgs_t) do -- spin through the list of error messages if v:find ('cs1-visible-error', 1, true) then -- look for the visible error class name hidden = false; -- found one; so don't hide the error message prefix break; -- and done because no need to look further end end z.error_msgs_t[1] = table.concat ({utilities.error_comment (msg_prefix, hidden), z.error_msgs_t[1]}); -- add error message prefix to first error message to prevent extraneous punctuation table.insert (render_t, table.concat (z.error_msgs_t, '; ')); -- make a big string of error messages and add it to the rendering end if 0 ~= #z.maint_cats_t then mw.addWarning (utilities.substitute (cfg.messages.warning_msg_m, template_link)); table.sort (z.maint_cats_t); -- sort the maintenance messages list local maint_msgs_t = {}; -- here we collect all of the maint messages if 0 == #z.error_msgs_t then -- if no error messages table.insert (maint_msgs_t, msg_prefix); -- insert message prefix in maint message livery end for _, v in ipairs( z.maint_cats_t ) do -- append maintenance categories table.insert (maint_msgs_t, -- assemble new maint message and add it to the maint_msgs_t table table.concat ({v, ' (', utilities.substitute (cfg.messages[':cat wikilink'], v), ')'}) ); end table.insert (render_t, utilities.substitute (cfg.presentation['hidden-maint'], table.concat (maint_msgs_t, ' '))); -- wrap the group of maint messages with proper presentation and save end if not no_tracking_cats then for _, v in ipairs (z.error_cats_t) do -- append error categories table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v)); end for _, v in ipairs (z.maint_cats_t) do -- append maintenance categories table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v)); end for _, v in ipairs (z.prop_cats_t) do -- append properties categories table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v)); end end return table.concat (render_t); -- make a big string and done end --[[--------------------------< V A L I D A T E >-------------------------------------------------------------- Looks for a parameter's name in one of several whitelists. Parameters in the whitelist can have three values: true - active, supported parameters false - deprecated, supported parameters nil - unsupported parameters ]] local function validate (name, cite_class, empty) local name = tostring (name); local enum_name; -- for enumerated parameters, is name with enumerator replaced with '#' local state; local function state_test (state, name) -- local function to do testing of state values if true == state then return true; end -- valid actively supported parameter if false == state then if empty then return nil; end -- empty deprecated parameters are treated as unknowns deprecated_parameter (name); -- parameter is deprecated but still supported return true; end if 'tracked' == state then local base_name = name:gsub ('%d', ''); -- strip enumerators from parameter names that have them to get the base name utilities.add_prop_cat ('tracked-param', {base_name}, base_name); -- add a properties category; <base_name> modifies <key> return true; end return nil; end if name:find ('#') then -- # is a cs1|2 reserved character so parameters with # not permitted return nil; end if utilities.in_array (cite_class, whitelist.preprint_template_list ) then -- limited parameter sets allowed for these templates state = whitelist.limited_basic_arguments[name]; if true == state_test (state, name) then return true; end state = whitelist.preprint_arguments[cite_class][name]; -- look in the parameter-list for the template identified by cite_class if true == state_test (state, name) then return true; end -- limited enumerated parameters list enum_name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) state = whitelist.limited_numbered_arguments[enum_name]; if true == state_test (state, name) then return true; end return false; -- not supported because not found or name is set to nil end -- end limited parameter-set templates if utilities.in_array (cite_class, whitelist.unique_param_template_list) then -- experiment for template-specific parameters for templates that accept parameters from the basic argument list state = whitelist.unique_arguments[cite_class][name]; -- look in the template-specific parameter-lists for the template identified by cite_class if true == state_test (state, name) then return true; end end -- if here, fall into general validation state = whitelist.basic_arguments[name]; -- all other templates; all normal parameters allowed if true == state_test (state, name) then return true; end -- all enumerated parameters allowed enum_name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) state = whitelist.numbered_arguments[enum_name]; if true == state_test (state, name) then return true; end return false; -- not supported because not found or name is set to nil end --[=[-------------------------< I N T E R _ W I K I _ C H E C K >---------------------------------------------- check <value> for inter-language interwiki-link markup. <prefix> must be a MediaWiki-recognized language code. when these values have the form (without leading colon): [[<prefix>:link|label]] return label as plain-text [[<prefix>:link]] return <prefix>:link as plain-text return value as is else ]=] local function inter_wiki_check (parameter, value) local prefix = value:match ('%[%[(%a+):'); -- get an interwiki prefix if one exists local _; if prefix and cfg.inter_wiki_map[prefix:lower()] then -- if prefix is in the map, needs preceding colon so utilities.set_message ('err_bad_paramlink', parameter); -- emit an error message _, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink end return value; end --[[--------------------------< M I S S I N G _ P I P E _ C H E C K >------------------------------------------ Look at the contents of a parameter. If the content has a string of characters and digits followed by an equal sign, compare the alphanumeric string to the list of cs1|2 parameters. If found, then the string is possibly a parameter that is missing its pipe. There are two tests made: {{cite ... |title=Title access-date=2016-03-17}} -- the first parameter has a value and whitespace separates that value from the missing pipe parameter name {{cite ... |title=access-date=2016-03-17}} -- the first parameter has no value (whitespace after the first = is trimmed by MediaWiki) cs1|2 shares some parameter names with XML/HTML attributes: class=, title=, etc. To prevent false positives XML/HTML tags are removed before the search. If a missing pipe is detected, this function adds the missing pipe maintenance category. ]] local function missing_pipe_check (parameter, value) local capture; value = value:gsub ('%b<>', ''); -- remove XML/HTML tags because attributes: class=, title=, etc. capture = value:match ('%s+(%a[%w%-]+)%s*=') or value:match ('^(%a[%w%-]+)%s*='); -- find and categorize parameters with possible missing pipes if capture and validate (capture) then -- if the capture is a valid parameter name utilities.set_message ('err_missing_pipe', parameter); end end --[[--------------------------< H A S _ E X T R A N E O U S _ P U N C T >-------------------------------------- look for extraneous terminal punctuation in most parameter values; parameters listed in skip table are not checked ]] local function has_extraneous_punc (param, value) if 'number' == type (param) then return; end param = param:gsub ('%d+', '#'); -- enumerated name-list mask params allow terminal punct; normalize if cfg.punct_skip[param] then return; -- parameter name found in the skip table so done end if value:match ('[,;:]$') then utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat end if value:match ('^=') then -- sometimes an extraneous '=' character appears ... utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat end end --[[--------------------------< H A S _ E X T R A N E O U S _ U R L >------------------------------------------ look for extraneous url parameter values; parameters listed in skip table are not checked ]] local function has_extraneous_url (url_param_t) local url_error_t = {}; check_for_url (url_param_t, url_error_t); -- extraneous url check if 0 ~= #url_error_t then -- non-zero when there are errors table.sort (url_error_t); utilities.set_message ('err_param_has_ext_link', {utilities.make_sep_list (#url_error_t, url_error_t)}); -- add this error message end end --[[--------------------------< C I T A T I O N >-------------------------------------------------------------- This is used by templates such as {{cite book}} to create the actual citation text. ]] local function citation(frame) Frame = frame; -- save a copy in case we need to display an error message in preview mode local sandbox = '/sandbox' -- i18n: replace this rvalue with the name that your wiki uses to identify sandbox subpages is_sandbox = nil ~= string.find (frame:getTitle(), sandbox, 1, true); -- is this invoke the sandbox module? sandbox = is_sandbox and sandbox or ''; -- use i18n sandbox to load sandbox modules when this module is the sandox; live modules else local pframe = frame:getParent() local styles; cfg = mw.loadData ('Module:Citation/CS1/Configuration' .. sandbox); -- load sandbox versions of support modules when {{#invoke:Citation/CS1/sandbox|...}}; live modules else whitelist = mw.loadData ('Module:Citation/CS1/Whitelist' .. sandbox); utilities = require ('Module:Citation/CS1/Utilities' .. sandbox); validation = require ('Module:Citation/CS1/Date_validation' .. sandbox); identifiers = require ('Module:Citation/CS1/Identifiers' .. sandbox); metadata = require ('Module:Citation/CS1/COinS' .. sandbox); styles = 'Module:Citation/CS1' .. sandbox .. '/styles.css'; utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the selected cfg tables identifiers.set_selected_modules (cfg, utilities); -- so that functions in Identifiers can see the selected cfg tables and selected Utilities module validation.set_selected_modules (cfg, utilities); -- so that functions in Date validataion can see selected cfg tables and the selected Utilities module metadata.set_selected_modules (cfg, utilities); -- so that functions in COinS can see the selected cfg tables and selected Utilities module z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities is_preview_mode = not utilities.is_set (frame:preprocess ('{{REVISIONID}}')); local args = {}; -- table where we store all of the template's arguments local suggestions = {}; -- table where we store suggestions if we need to loadData them local error_text; -- used as a flag local config = {}; -- table to store parameters from the module {{#invoke:}} for k, v in pairs( frame.args ) do -- get parameters from the {{#invoke}} frame config[k] = v; -- args[k] = v; -- crude debug support that allows us to render a citation from module {{#invoke:}}; skips parameter validation; TODO: keep? end local capture; -- the single supported capture when matching unknown parameters using patterns local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing for k, v in pairs( pframe.args ) do -- get parameters from the parent (template) frame v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string if v ~= '' then if ('string' == type (k)) then k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- for enumerated parameters, translate 'local' digits to Western 0-9 end if not validate( k, config.CitationClass ) then if type (k) ~= 'string' then -- exclude empty numbered parameters if v:match("%S+") ~= nil then error_text = utilities.set_message ('err_text_ignored', {v}); end elseif validate (k:lower(), config.CitationClass) then error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, k:lower()}); -- suggest the lowercase version of the parameter else if nil == suggestions.suggestions then -- if this table is nil then we need to load it if is_sandbox then -- did the {{#invoke:}} use sandbox version? suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions/sandbox' ); -- use the sandbox version else suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions' ); -- use the live version end end for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter capture = k:match (pattern); -- the whole match if no capture in pattern else the capture if a match if capture then -- if the pattern matches param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator) if validate (param, config.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists) error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, param}); -- set the suggestion error message else error_text = utilities.set_message ('err_parameter_ignored', {k}); -- suggested param not supported by this template v = ''; -- unset end end end if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion? if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config.CitationClass) then utilities.set_message ('err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}); else utilities.set_message ('err_parameter_ignored', {k}); v = ''; -- unset value assigned to unrecognized parameters (this for the limited parameter lists) end end end end args[k] = v; -- save this parameter and its value elseif not utilities.is_set (v) then -- for empty parameters if not validate (k, config.CitationClass, true) then -- is this empty parameter a valid parameter k = ('' == k) and '(empty string)' or k; -- when k is empty string (or was space(s) trimmed to empty string), replace with descriptive text table.insert (empty_unknowns, utilities.wrap_style ('parameter', k)); -- format for error message and add to the list end -- crude debug support that allows us to render a citation from module {{#invoke:}} TODO: keep? -- elseif args[k] ~= nil or (k == 'postscript') then -- when args[k] has a value from {{#invoke}} frame (we don't normally do that) -- args[k] = v; -- overwrite args[k] with empty string from pframe.args[k] (template frame); v is empty string here end -- not sure about the postscript bit; that gets handled in parameter validation; historical artifact? end if 0 ~= #empty_unknowns then -- create empty unknown error message utilities.set_message ('err_param_unknown_empty', { 1 == #empty_unknowns and '' or 's', utilities.make_sep_list (#empty_unknowns, empty_unknowns) }); end local url_param_t = {}; for k, v in pairs( args ) do if 'string' == type (k) then -- don't evaluate positional parameters has_invisible_chars (k, v); -- look for invisible characters end has_extraneous_punc (k, v); -- look for extraneous terminal punctuation in parameter values missing_pipe_check (k, v); -- do we think that there is a parameter that is missing a pipe? args[k] = inter_wiki_check (k, v); -- when language interwiki-linked parameter missing leading colon replace with wiki-link label if 'string' == type (k) and not cfg.url_skip[k] then -- when parameter k is not positional and not in url skip table url_param_t[k] = v; -- make a parameter/value list for extraneous url check end end has_extraneous_url (url_param_t); -- look for url in parameter values where a url does not belong return table.concat ({ frame:extensionTag ('templatestyles', '', {src=styles}), citation0( config, args) }); end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return {citation = citation}; 5b914afd20bdaa8daab7192c9ee32f246e5bee9b Albert Einstein 0 13 23 2022-07-02T03:18:28Z SpaceMan 2 Albert Einstein wikitext text/x-wiki Albert Einstein was born at Ulm, in Württemberg, Germany, on March 14, 1879. Six weeks later the family moved to Munich, where he later on began his schooling at the Luitpold Gymnasium. Later, they moved to Italy and Albert continued his education at Aarau, Switzerland and in 1896 he entered the Swiss Federal Polytechnic School in Zurich to be trained as a teacher in physics and mathematics. In 1901, the year he gained his diploma, he acquired Swiss citizenship and, as he was unable to find a teaching post, he accepted a position as technical assistant in the Swiss Patent Office. In 1905 he obtained his doctor’s degree. During his stay at the Patent Office, and in his spare time, he produced much of his remarkable work and in 1908 he was appointed Privatdozent in Berne. In 1909 he became Professor Extraordinary at Zurich, in 1911 Professor of Theoretical Physics at Prague, returning to Zurich in the following year to fill a similar post. In 1914 he was appointed Director of the Kaiser Wilhelm Physical Institute and Professor in the University of Berlin. He became a German citizen in 1914 and remained in Berlin until 1933 when he renounced his citizenship for political reasons and emigrated to America to take the position of Professor of Theoretical Physics at Princeton*. He became a United States citizen in 1940 and retired from his post in 1945. After World War II, Einstein was a leading figure in the World Government Movement, he was offered the Presidency of the State of Israel, which he declined, and he collaborated with Dr. Chaim Weizmann in establishing the Hebrew University of Jerusalem. Einstein always appeared to have a clear view of the problems of physics and the determination to solve them. He had a strategy of his own and was able to visualize the main stages on the way to his goal. He regarded his major achievements as mere stepping-stones for the next advance. At the start of his scientific work, Einstein realized the inadequacies of Newtonian mechanics and his special theory of relativity stemmed from an attempt to reconcile the laws of mechanics with the laws of the electromagnetic field. He dealt with classical problems of statistical mechanics and problems in which they were merged with quantum theory: this led to an explanation of the Brownian movement of molecules. He investigated the thermal properties of light with a low radiation density and his observations laid the foundation of the photon theory of light. In his early days in Berlin, Einstein postulated that the correct interpretation of the special theory of relativity must also furnish a theory of gravitation and in 1916 he published his paper on the general theory of relativity. During this time he also contributed to the problems of the theory of radiation and statistical mechanics. In the 1920s, Einstein embarked on the construction of unified field theories, although he continued to work on the probabilistic interpretation of quantum theory, and he persevered with this work in America. He contributed to statistical mechanics by his development of the quantum theory of a monatomic gas and he has also accomplished valuable work in connection with atomic transition probabilities and relativistic cosmology. After his retirement he continued to work towards the unification of the basic concepts of physics, taking the opposite approach, geometrisation, to the majority of physicists. Einstein’s researches are, of course, well chronicled and his more important works include Special Theory of Relativity (1905), Relativity (English translations, 1920 and 1950), General Theory of Relativity (1916), Investigations on Theory of Brownian Movement (1926), and The Evolution of Physics (1938). Among his non-scientific works, About Zionism (1930), Why War? (1933), My Philosophy (1934), and Out of My Later Years (1950) are perhaps the most important. Albert Einstein received honorary doctorate degrees in science, medicine and philosophy from many European and American universities. During the 1920’s he lectured in Europe, America and the Far East, and he was awarded Fellowships or Memberships of all the leading scientific academies throughout the world. He gained numerous awards in recognition of his work, including the Copley Medal of the Royal Society of London in 1925, and the Franklin Medal of the Franklin Institute in 1935. Einstein’s gifts inevitably resulted in his dwelling much in intellectual solitude and, for relaxation, music played an important part in his life. He married Mileva Maric in 1903 and they had a daughter and two sons; their marriage was dissolved in 1919 and in the same year he married his cousin, Elsa Löwenthal, who died in 1936. He died on April 18, 1955 at Princeton, New Jersey. === Works === [[Relativity]] a8d4b1f819de9f8b0e75f7f7b5315dc62869cab8 25 23 2022-07-02T03:21:48Z SpaceMan 2 wikitext text/x-wiki [[File:AlbertE.jpg|thumb|Albert Einstein]] Albert Einstein was born at Ulm, in Württemberg, Germany, on March 14, 1879. Six weeks later the family moved to Munich, where he later on began his schooling at the Luitpold Gymnasium. Later, they moved to Italy and Albert continued his education at Aarau, Switzerland and in 1896 he entered the Swiss Federal Polytechnic School in Zurich to be trained as a teacher in physics and mathematics. In 1901, the year he gained his diploma, he acquired Swiss citizenship and, as he was unable to find a teaching post, he accepted a position as technical assistant in the Swiss Patent Office. In 1905 he obtained his doctor’s degree. During his stay at the Patent Office, and in his spare time, he produced much of his remarkable work and in 1908 he was appointed Privatdozent in Berne. In 1909 he became Professor Extraordinary at Zurich, in 1911 Professor of Theoretical Physics at Prague, returning to Zurich in the following year to fill a similar post. In 1914 he was appointed Director of the Kaiser Wilhelm Physical Institute and Professor in the University of Berlin. He became a German citizen in 1914 and remained in Berlin until 1933 when he renounced his citizenship for political reasons and emigrated to America to take the position of Professor of Theoretical Physics at Princeton*. He became a United States citizen in 1940 and retired from his post in 1945. After World War II, Einstein was a leading figure in the World Government Movement, he was offered the Presidency of the State of Israel, which he declined, and he collaborated with Dr. Chaim Weizmann in establishing the Hebrew University of Jerusalem. Einstein always appeared to have a clear view of the problems of physics and the determination to solve them. He had a strategy of his own and was able to visualize the main stages on the way to his goal. He regarded his major achievements as mere stepping-stones for the next advance. At the start of his scientific work, Einstein realized the inadequacies of Newtonian mechanics and his special theory of relativity stemmed from an attempt to reconcile the laws of mechanics with the laws of the electromagnetic field. He dealt with classical problems of statistical mechanics and problems in which they were merged with quantum theory: this led to an explanation of the Brownian movement of molecules. He investigated the thermal properties of light with a low radiation density and his observations laid the foundation of the photon theory of light. In his early days in Berlin, Einstein postulated that the correct interpretation of the special theory of relativity must also furnish a theory of gravitation and in 1916 he published his paper on the general theory of relativity. During this time he also contributed to the problems of the theory of radiation and statistical mechanics. In the 1920s, Einstein embarked on the construction of unified field theories, although he continued to work on the probabilistic interpretation of quantum theory, and he persevered with this work in America. He contributed to statistical mechanics by his development of the quantum theory of a monatomic gas and he has also accomplished valuable work in connection with atomic transition probabilities and relativistic cosmology. After his retirement he continued to work towards the unification of the basic concepts of physics, taking the opposite approach, geometrisation, to the majority of physicists. Einstein’s researches are, of course, well chronicled and his more important works include Special Theory of Relativity (1905), Relativity (English translations, 1920 and 1950), General Theory of Relativity (1916), Investigations on Theory of Brownian Movement (1926), and The Evolution of Physics (1938). Among his non-scientific works, About Zionism (1930), Why War? (1933), My Philosophy (1934), and Out of My Later Years (1950) are perhaps the most important. Albert Einstein received honorary doctorate degrees in science, medicine and philosophy from many European and American universities. During the 1920’s he lectured in Europe, America and the Far East, and he was awarded Fellowships or Memberships of all the leading scientific academies throughout the world. He gained numerous awards in recognition of his work, including the Copley Medal of the Royal Society of London in 1925, and the Franklin Medal of the Franklin Institute in 1935. Einstein’s gifts inevitably resulted in his dwelling much in intellectual solitude and, for relaxation, music played an important part in his life. He married Mileva Maric in 1903 and they had a daughter and two sons; their marriage was dissolved in 1919 and in the same year he married his cousin, Elsa Löwenthal, who died in 1936. He died on April 18, 1955 at Princeton, New Jersey. === Works === [[Relativity]] afdccbf5e5b556ebc4660e527d3ee43dd582c518 26 25 2022-07-02T03:27:22Z SpaceMan 2 wikitext text/x-wiki [[File:AlbertE.jpg|thumb|Albert Einstein]] Albert Einstein was born at Ulm, in Württemberg, Germany, on March 14, 1879. Six weeks later the family moved to Munich, where he later on began his schooling at the Luitpold Gymnasium. Later, they moved to Italy and Albert continued his education at Aarau, Switzerland and in 1896 he entered the Swiss Federal Polytechnic School in Zurich to be trained as a teacher in physics and mathematics. In 1901, the year he gained his diploma, he acquired Swiss citizenship and, as he was unable to find a teaching post, he accepted a position as technical assistant in the Swiss Patent Office. In 1905 he obtained his doctor’s degree. During his stay at the Patent Office, and in his spare time, he produced much of his remarkable work and in 1908 he was appointed Privatdozent in Berne. In 1909 he became Professor Extraordinary at Zurich, in 1911 Professor of Theoretical Physics at Prague, returning to Zurich in the following year to fill a similar post. In 1914 he was appointed Director of the Kaiser Wilhelm Physical Institute and Professor in the University of Berlin. He became a German citizen in 1914 and remained in Berlin until 1933 when he renounced his citizenship for political reasons and emigrated to America to take the position of Professor of Theoretical Physics at Princeton*. He became a United States citizen in 1940 and retired from his post in 1945. After World War II, Einstein was a leading figure in the World Government Movement, he was offered the Presidency of the State of Israel, which he declined, and he collaborated with Dr. Chaim Weizmann in establishing the Hebrew University of Jerusalem. Einstein always appeared to have a clear view of the problems of physics and the determination to solve them. He had a strategy of his own and was able to visualize the main stages on the way to his goal. He regarded his major achievements as mere stepping-stones for the next advance. At the start of his scientific work, Einstein realized the inadequacies of Newtonian mechanics and his special theory of relativity stemmed from an attempt to reconcile the laws of mechanics with the laws of the electromagnetic field. He dealt with classical problems of statistical mechanics and problems in which they were merged with quantum theory: this led to an explanation of the Brownian movement of molecules. He investigated the thermal properties of light with a low radiation density and his observations laid the foundation of the photon theory of light. In his early days in Berlin, Einstein postulated that the correct interpretation of the special theory of relativity must also furnish a theory of gravitation and in 1916 he published his paper on the general theory of relativity. During this time he also contributed to the problems of the theory of radiation and statistical mechanics. In the 1920s, Einstein embarked on the construction of unified field theories, although he continued to work on the probabilistic interpretation of quantum theory, and he persevered with this work in America. He contributed to statistical mechanics by his development of the quantum theory of a monatomic gas and he has also accomplished valuable work in connection with atomic transition probabilities and relativistic cosmology. After his retirement he continued to work towards the unification of the basic concepts of physics, taking the opposite approach, geometrisation, to the majority of physicists. Einstein’s researches are, of course, well chronicled and his more important works include Special Theory of Relativity (1905), Relativity (English translations, 1920 and 1950), General Theory of Relativity (1916), Investigations on Theory of Brownian Movement (1926), and The Evolution of Physics (1938). Among his non-scientific works, About Zionism (1930), Why War? (1933), My Philosophy (1934), and Out of My Later Years (1950) are perhaps the most important. Albert Einstein received honorary doctorate degrees in science, medicine and philosophy from many European and American universities. During the 1920’s he lectured in Europe, America and the Far East, and he was awarded Fellowships or Memberships of all the leading scientific academies throughout the world. He gained numerous awards in recognition of his work, including the Copley Medal of the Royal Society of London in 1925, and the Franklin Medal of the Franklin Institute in 1935. Einstein’s gifts inevitably resulted in his dwelling much in intellectual solitude and, for relaxation, music played an important part in his life. He married Mileva Maric in 1903 and they had a daughter and two sons; their marriage was dissolved in 1919 and in the same year he married his cousin, Elsa Löwenthal, who died in 1936. He died on April 18, 1955 at Princeton, New Jersey. === Works === [[Relativity]] 51f57e555efb1217535a6b269fb687a83b8c351e 27 26 2022-07-02T03:33:39Z SpaceMan 2 wikitext text/x-wiki [[File:AlbertE.jpg|thumb|Albert Einstein]] {| class="wikitable" |- ! Born ! 14 March 1879<br />Ulm, Kingdom of Württemberg, German Empire |- | Died | 18 April 1955 (aged 76)<br />Princeton, New Jersey, U.S. |- style="text-align:center;" | Known for | style="text-align:left;" | General relativity<br />Special relativity<br />Photoelectric effect<br />E=mc2 (Mass–energy equivalence)<br />E=hf (Planck–Einstein relation)<br />Theory of Brownian motion<br />Einstein field equations<br />Bose–Einstein statistics<br />Bose–Einstein condensate<br />Gravitational wave<br />Cosmological constant<br />Unified field theory<br />EPR paradox<br />Ensemble interpretation<br />List of other concepts |} Albert Einstein was born at Ulm, in Württemberg, Germany, on March 14, 1879. Six weeks later the family moved to Munich, where he later on began his schooling at the Luitpold Gymnasium. Later, they moved to Italy and Albert continued his education at Aarau, Switzerland and in 1896 he entered the Swiss Federal Polytechnic School in Zurich to be trained as a teacher in physics and mathematics. In 1901, the year he gained his diploma, he acquired Swiss citizenship and, as he was unable to find a teaching post, he accepted a position as technical assistant in the Swiss Patent Office. In 1905 he obtained his doctor’s degree. During his stay at the Patent Office, and in his spare time, he produced much of his remarkable work and in 1908 he was appointed Privatdozent in Berne. In 1909 he became Professor Extraordinary at Zurich, in 1911 Professor of Theoretical Physics at Prague, returning to Zurich in the following year to fill a similar post. In 1914 he was appointed Director of the Kaiser Wilhelm Physical Institute and Professor in the University of Berlin. He became a German citizen in 1914 and remained in Berlin until 1933 when he renounced his citizenship for political reasons and emigrated to America to take the position of Professor of Theoretical Physics at Princeton*. He became a United States citizen in 1940 and retired from his post in 1945. After World War II, Einstein was a leading figure in the World Government Movement, he was offered the Presidency of the State of Israel, which he declined, and he collaborated with Dr. Chaim Weizmann in establishing the Hebrew University of Jerusalem. Einstein always appeared to have a clear view of the problems of physics and the determination to solve them. He had a strategy of his own and was able to visualize the main stages on the way to his goal. He regarded his major achievements as mere stepping-stones for the next advance. At the start of his scientific work, Einstein realized the inadequacies of Newtonian mechanics and his special theory of relativity stemmed from an attempt to reconcile the laws of mechanics with the laws of the electromagnetic field. He dealt with classical problems of statistical mechanics and problems in which they were merged with quantum theory: this led to an explanation of the Brownian movement of molecules. He investigated the thermal properties of light with a low radiation density and his observations laid the foundation of the photon theory of light. In his early days in Berlin, Einstein postulated that the correct interpretation of the special theory of relativity must also furnish a theory of gravitation and in 1916 he published his paper on the general theory of relativity. During this time he also contributed to the problems of the theory of radiation and statistical mechanics. In the 1920s, Einstein embarked on the construction of unified field theories, although he continued to work on the probabilistic interpretation of quantum theory, and he persevered with this work in America. He contributed to statistical mechanics by his development of the quantum theory of a monatomic gas and he has also accomplished valuable work in connection with atomic transition probabilities and relativistic cosmology. After his retirement he continued to work towards the unification of the basic concepts of physics, taking the opposite approach, geometrisation, to the majority of physicists. Einstein’s researches are, of course, well chronicled and his more important works include Special Theory of Relativity (1905), Relativity (English translations, 1920 and 1950), General Theory of Relativity (1916), Investigations on Theory of Brownian Movement (1926), and The Evolution of Physics (1938). Among his non-scientific works, About Zionism (1930), Why War? (1933), My Philosophy (1934), and Out of My Later Years (1950) are perhaps the most important. Albert Einstein received honorary doctorate degrees in science, medicine and philosophy from many European and American universities. During the 1920’s he lectured in Europe, America and the Far East, and he was awarded Fellowships or Memberships of all the leading scientific academies throughout the world. He gained numerous awards in recognition of his work, including the Copley Medal of the Royal Society of London in 1925, and the Franklin Medal of the Franklin Institute in 1935. Einstein’s gifts inevitably resulted in his dwelling much in intellectual solitude and, for relaxation, music played an important part in his life. He married Mileva Maric in 1903 and they had a daughter and two sons; their marriage was dissolved in 1919 and in the same year he married his cousin, Elsa Löwenthal, who died in 1936. He died on April 18, 1955 at Princeton, New Jersey. === Works === [[Relativity]] 7ffc6859fae04e428dce9ffc3b6b531f1b58baed 28 27 2022-07-02T03:34:35Z SpaceMan 2 Protected "[[Albert Einstein]]" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) wikitext text/x-wiki [[File:AlbertE.jpg|thumb|Albert Einstein]] {| class="wikitable" |- ! Born ! 14 March 1879<br />Ulm, Kingdom of Württemberg, German Empire |- | Died | 18 April 1955 (aged 76)<br />Princeton, New Jersey, U.S. |- style="text-align:center;" | Known for | style="text-align:left;" | General relativity<br />Special relativity<br />Photoelectric effect<br />E=mc2 (Mass–energy equivalence)<br />E=hf (Planck–Einstein relation)<br />Theory of Brownian motion<br />Einstein field equations<br />Bose–Einstein statistics<br />Bose–Einstein condensate<br />Gravitational wave<br />Cosmological constant<br />Unified field theory<br />EPR paradox<br />Ensemble interpretation<br />List of other concepts |} Albert Einstein was born at Ulm, in Württemberg, Germany, on March 14, 1879. Six weeks later the family moved to Munich, where he later on began his schooling at the Luitpold Gymnasium. Later, they moved to Italy and Albert continued his education at Aarau, Switzerland and in 1896 he entered the Swiss Federal Polytechnic School in Zurich to be trained as a teacher in physics and mathematics. In 1901, the year he gained his diploma, he acquired Swiss citizenship and, as he was unable to find a teaching post, he accepted a position as technical assistant in the Swiss Patent Office. In 1905 he obtained his doctor’s degree. During his stay at the Patent Office, and in his spare time, he produced much of his remarkable work and in 1908 he was appointed Privatdozent in Berne. In 1909 he became Professor Extraordinary at Zurich, in 1911 Professor of Theoretical Physics at Prague, returning to Zurich in the following year to fill a similar post. In 1914 he was appointed Director of the Kaiser Wilhelm Physical Institute and Professor in the University of Berlin. He became a German citizen in 1914 and remained in Berlin until 1933 when he renounced his citizenship for political reasons and emigrated to America to take the position of Professor of Theoretical Physics at Princeton*. He became a United States citizen in 1940 and retired from his post in 1945. After World War II, Einstein was a leading figure in the World Government Movement, he was offered the Presidency of the State of Israel, which he declined, and he collaborated with Dr. Chaim Weizmann in establishing the Hebrew University of Jerusalem. Einstein always appeared to have a clear view of the problems of physics and the determination to solve them. He had a strategy of his own and was able to visualize the main stages on the way to his goal. He regarded his major achievements as mere stepping-stones for the next advance. At the start of his scientific work, Einstein realized the inadequacies of Newtonian mechanics and his special theory of relativity stemmed from an attempt to reconcile the laws of mechanics with the laws of the electromagnetic field. He dealt with classical problems of statistical mechanics and problems in which they were merged with quantum theory: this led to an explanation of the Brownian movement of molecules. He investigated the thermal properties of light with a low radiation density and his observations laid the foundation of the photon theory of light. In his early days in Berlin, Einstein postulated that the correct interpretation of the special theory of relativity must also furnish a theory of gravitation and in 1916 he published his paper on the general theory of relativity. During this time he also contributed to the problems of the theory of radiation and statistical mechanics. In the 1920s, Einstein embarked on the construction of unified field theories, although he continued to work on the probabilistic interpretation of quantum theory, and he persevered with this work in America. He contributed to statistical mechanics by his development of the quantum theory of a monatomic gas and he has also accomplished valuable work in connection with atomic transition probabilities and relativistic cosmology. After his retirement he continued to work towards the unification of the basic concepts of physics, taking the opposite approach, geometrisation, to the majority of physicists. Einstein’s researches are, of course, well chronicled and his more important works include Special Theory of Relativity (1905), Relativity (English translations, 1920 and 1950), General Theory of Relativity (1916), Investigations on Theory of Brownian Movement (1926), and The Evolution of Physics (1938). Among his non-scientific works, About Zionism (1930), Why War? (1933), My Philosophy (1934), and Out of My Later Years (1950) are perhaps the most important. Albert Einstein received honorary doctorate degrees in science, medicine and philosophy from many European and American universities. During the 1920’s he lectured in Europe, America and the Far East, and he was awarded Fellowships or Memberships of all the leading scientific academies throughout the world. He gained numerous awards in recognition of his work, including the Copley Medal of the Royal Society of London in 1925, and the Franklin Medal of the Franklin Institute in 1935. Einstein’s gifts inevitably resulted in his dwelling much in intellectual solitude and, for relaxation, music played an important part in his life. He married Mileva Maric in 1903 and they had a daughter and two sons; their marriage was dissolved in 1919 and in the same year he married his cousin, Elsa Löwenthal, who died in 1936. He died on April 18, 1955 at Princeton, New Jersey. === Works === [[Relativity]] 7ffc6859fae04e428dce9ffc3b6b531f1b58baed File:AlbertE.jpg 6 14 24 2022-07-02T03:20:47Z SpaceMan 2 Uploaded own work with UploadWizard wikitext text/x-wiki =={{int:filedesc}}== {{Information |description={{en|1=Albert Einstein}} |date=2022-07-02 |source={{own}} |author=[[User:SpaceMan|Astrobase ]] |permission= |other versions= }} =={{int:license-header}}== {{self|cc-by-sa-4.0}} [[Category:Scientist]] f6767cfb3458fd6198b477e4c6897767651fc5c0 Relativity 0 15 29 2022-07-02T03:36:21Z SpaceMan 2 Created page with "General relativity is concerned with [[gravity]], one of the fundamental forces in the universe. Gravity defines macroscopic behaviour, and so general relativity describes large-scale physical phenomena. It was conceived by [[Albert Einstein]] in 1916 General relativity follows from Einstein’s principle of equivalence: on a local scale it is impossible to distinguish between physical effects due to gravity and those due to acceleration. Gravity is treated as a geome..." wikitext text/x-wiki General relativity is concerned with [[gravity]], one of the fundamental forces in the universe. Gravity defines macroscopic behaviour, and so general relativity describes large-scale physical phenomena. It was conceived by [[Albert Einstein]] in 1916 General relativity follows from Einstein’s principle of equivalence: on a local scale it is impossible to distinguish between physical effects due to gravity and those due to acceleration. Gravity is treated as a geometric phenomenon that arises from the curvature of space-time. The solution of the field equations that describe general relativity can yield answers to different physical situations, such as planetary dynamics, the birth and death of [[stars]], [[black holes]], and the evolution of the universe. General relativity has been experimentally verified by observations of gravitational lenses, the orbit of the planet [[Mercury]], the dilation of time in Earth’s gravitational field, and gravitational waves from merging black holes. 9f183f4d6800a1df9b286767c4660838da6d15a5 SpaceMan:General disclaimer 4 16 31 2022-07-02T04:38:48Z SpaceMan 2 Disclaimer wikitext text/x-wiki ===DISCLAIMER=== Last updated July 02, 2022 ===WEBSITE DISCLAIMER=== The information provided by Astrobase ('we', 'us', or 'our') on https://astrobase.miraheze.org/ (the 'Site') is for general informational purposes only. All information on the Site is provided in good faith. ===EXTERNAL LINKS DISCLAIMER=== The Site may contain (or you may be sent through the Site) links to other websites or content belonging to or originating from third parties or links to websites and features in banners or other advertising. Such external links are not investigated, monitored, or checked for accuracy, adequacy, validity, reliability, availability, or completeness by us. WE DO NOT WARRANT, ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR THE ACCURACY OR RELIABILITY OF ANY INFORMATION OFFERED BY THIRD-PARTY WEBSITES LINKED THROUGH THE SITE OR ANY WEBSITE OR FEATURE LINKED IN ANY BANNER OR OTHER ADVERTISING. WE WILL NOT BE A PARTY TO OR IN ANY WAY BE RESPONSIBLE FOR MONITORING ANY TRANSACTION BETWEEN YOU AND THIRD-PARTY PROVIDERS OF PRODUCTS OR SERVICES. ===PROFESSIONAL DISCLAIMER=== The Site cannot and does not contain science advice. The science information is provided for general informational and educational purposes only and is not a substitute for professional advice. Accordingly, before taking any actions based upon such information, we encourage you to consult with the appropriate professionals. We do not provide any kind of science advice. THE USE OR RELIANCE OF ANY INFORMATION CONTAINED ON THE SITE IS SOLELY AT YOUR OWN RISK. 9137a48227cc9ce58e1382afd7c0c6acc9d47970 32 31 2022-07-02T04:39:57Z SpaceMan 2 Protected "[[AstroBase:General disclaimer]]" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) wikitext text/x-wiki ===DISCLAIMER=== Last updated July 02, 2022 ===WEBSITE DISCLAIMER=== The information provided by Astrobase ('we', 'us', or 'our') on https://astrobase.miraheze.org/ (the 'Site') is for general informational purposes only. All information on the Site is provided in good faith. ===EXTERNAL LINKS DISCLAIMER=== The Site may contain (or you may be sent through the Site) links to other websites or content belonging to or originating from third parties or links to websites and features in banners or other advertising. Such external links are not investigated, monitored, or checked for accuracy, adequacy, validity, reliability, availability, or completeness by us. WE DO NOT WARRANT, ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR THE ACCURACY OR RELIABILITY OF ANY INFORMATION OFFERED BY THIRD-PARTY WEBSITES LINKED THROUGH THE SITE OR ANY WEBSITE OR FEATURE LINKED IN ANY BANNER OR OTHER ADVERTISING. WE WILL NOT BE A PARTY TO OR IN ANY WAY BE RESPONSIBLE FOR MONITORING ANY TRANSACTION BETWEEN YOU AND THIRD-PARTY PROVIDERS OF PRODUCTS OR SERVICES. ===PROFESSIONAL DISCLAIMER=== The Site cannot and does not contain science advice. The science information is provided for general informational and educational purposes only and is not a substitute for professional advice. Accordingly, before taking any actions based upon such information, we encourage you to consult with the appropriate professionals. We do not provide any kind of science advice. THE USE OR RELIANCE OF ANY INFORMATION CONTAINED ON THE SITE IS SOLELY AT YOUR OWN RISK. 9137a48227cc9ce58e1382afd7c0c6acc9d47970 SpaceMan:Copyrights 4 17 33 2022-07-02T04:43:41Z SpaceMan 2 Copyright wikitext text/x-wiki ===Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)=== This is a human-readable summary of (and not a substitute for) the license. Disclaimer. You are free to: Share — copy and redistribute the material in any medium or format Adapt — remix, transform, and build upon the material for any purpose, even commercially. The licensor cannot revoke these freedoms as long as you follow the license terms. ===Under the following terms:=== Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. fa8920aeca08f6d853143e56c2adbea7d9b92f28 34 33 2022-07-02T04:43:57Z SpaceMan 2 Protected "[[AstroBase:Copyrights]]" ([Edit=Allow only administrators] (indefinite)) wikitext text/x-wiki ===Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)=== This is a human-readable summary of (and not a substitute for) the license. Disclaimer. You are free to: Share — copy and redistribute the material in any medium or format Adapt — remix, transform, and build upon the material for any purpose, even commercially. The licensor cannot revoke these freedoms as long as you follow the license terms. ===Under the following terms:=== Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. fa8920aeca08f6d853143e56c2adbea7d9b92f28 Astronomy 0 10 35 19 2022-07-02T08:05:23Z SpaceMan 2 /* Definition */ wikitext text/x-wiki == Definition == * Astronomy (from Ancient Greek ἀστρονομία (astronomía) 'science that studies the laws of the stars') is a natural science that studies celestial objects and phenomena. It uses [[mathematics]], [[physics]], and <nowiki> [[chemistry]] </nowiki>in order to explain their origin and evolution. Objects of interest include [[planets]], [[moons]], [[stars]], [[nebulae]], [[galaxies]], and [[comets]]. Relevant phenomena include [[supernova explosions]], [[gamma ray bursts]], [[quasars]], [[blazars]], [[pulsars]], and [[cosmic microwave background radiation]]. More generally, astronomy studies everything that originates beyond Earth's atmosphere. Cosmology is a branch of astronomy that studies the universe as a whole. Astronomy is one of the oldest natural sciences. The early civilizations in recorded history made methodical observations of the night sky. These include the Babylonians, Greeks, Indians, Egyptians, Chinese, Maya, and many ancient indigenous peoples of the Americas. In the past, astronomy included disciplines as diverse as astrometry, celestial navigation, observational astronomy, and the making of calendars. Nowadays, professional astronomy is often said to be the same as astrophysics. Professional astronomy is split into observational and theoretical branches. Observational astronomy is focused on acquiring data from observations of astronomical objects. This data is then analyzed using basic principles of physics. Theoretical astronomy is oriented toward the development of computer or analytical models to describe astronomical objects and phenomena. These two fields complement each other. Theoretical astronomy seeks to explain observational results and observations are used to confirm theoretical results. Astronomy is one of the few sciences in which amateurs play an active role. This is especially true for the discovery and observation of transient events. Amateur astronomers have helped with many important discoveries, such as finding new comets. [[File:Astronomy.jpg|thumb|Astronomy picture]] 096c6b94e0f24eb914c9252595e6e0e08eb6cfbc Gravity 0 18 36 2022-07-02T08:08:39Z SpaceMan 2 Created page with "===Definition=== Gravitation is defined as the force of attraction between any two bodies in the universe. The earth attracts (or pulls) all objects lying on or near its surface towards its centre. The [[Force]] with which the earth pulls the objects towards its centre is called the gravitational force of the earth or gravity of the earth. ==Universal Law of Gravitation== Universal law of gravitation was given by *[[Isaac Newton]]. According to this law, the atractive..." wikitext text/x-wiki ===Definition=== Gravitation is defined as the force of attraction between any two bodies in the universe. The earth attracts (or pulls) all objects lying on or near its surface towards its centre. The [[Force]] with which the earth pulls the objects towards its centre is called the gravitational force of the earth or gravity of the earth. ==Universal Law of Gravitation== Universal law of gravitation was given by *[[Isaac Newton]]. According to this law, the atractive force between any two objects in the universe is directly proportional to the product of their masses([[Mass]]) and inversely proportional to the square of [[distance]] between them. e direction of the force is along the line joining the centres of two objects. ==Newton's law of universal gravitation== 1. Force is directly proportional to product of masses of bodies. 2. It is indirectly proportional to distance between bodies. 3. Formula for F = G*m1*m2/d² Where G is the constant of gravity and m1 and M2 are the masses of bodies and d² is the square of [[distance]] between them. 7249b23c7a172df6f5edfbf5f01f02a9fd1fd18e 37 36 2022-07-02T08:09:13Z SpaceMan 2 Protected "[[Gravity]]" ([Edit=Allow only autoconfirmed users] (indefinite) [Move=Allow only autoconfirmed users] (indefinite)) wikitext text/x-wiki ===Definition=== Gravitation is defined as the force of attraction between any two bodies in the universe. The earth attracts (or pulls) all objects lying on or near its surface towards its centre. The [[Force]] with which the earth pulls the objects towards its centre is called the gravitational force of the earth or gravity of the earth. ==Universal Law of Gravitation== Universal law of gravitation was given by *[[Isaac Newton]]. According to this law, the atractive force between any two objects in the universe is directly proportional to the product of their masses([[Mass]]) and inversely proportional to the square of [[distance]] between them. e direction of the force is along the line joining the centres of two objects. ==Newton's law of universal gravitation== 1. Force is directly proportional to product of masses of bodies. 2. It is indirectly proportional to distance between bodies. 3. Formula for F = G*m1*m2/d² Where G is the constant of gravity and m1 and M2 are the masses of bodies and d² is the square of [[distance]] between them. 7249b23c7a172df6f5edfbf5f01f02a9fd1fd18e Isaac Newton 0 19 38 2022-07-02T08:10:58Z SpaceMan 2 Created page with "Isaac was born in Woolsthorpe near Grantham, England. He is generally regarded as the most original and influential theorist in the history of [[science]]. He was born in a poor farming family. But he was not good at farming. He was sent to study at [[Cambridge University]] in 1661. In 1665 a plague broke out in Cambridge and so Newton took a year off. It was during this year that the incident of the apple falling on him is said to have occurred. This incident prompted N..." wikitext text/x-wiki Isaac was born in Woolsthorpe near Grantham, England. He is generally regarded as the most original and influential theorist in the history of [[science]]. He was born in a poor farming family. But he was not good at farming. He was sent to study at [[Cambridge University]] in 1661. In 1665 a plague broke out in Cambridge and so Newton took a year off. It was during this year that the incident of the apple falling on him is said to have occurred. This incident prompted Newton to explore the possibility of connecting [[gravity]] with the force that kept the tacon in its orbit. This led him to the universal law of gravitation. It is remarkable that many great scientists before him knew of gravity but failed to realise it. Newton formulated the well-known laws of motion. He worked on theories of light and colour. He designed an astronomical telescope to carry out astronomical observations. Newton was also a great mathematician. He invented a new branch of mathematics, called [[calculus]]. He used it to prove that for objects outside a sphere of uniform [[density]], the sphere behaves as if the whole of its mass is concentrated at its centre. Newton transformed the structure of physical science with his three laws of motion and the universal law of gravitation. As the keystone of the scientific revolution of the seventeenth century, Newton's work combined the contributions of [[Copernicus]], [[Kepler]], [[Galileo]], and others into a new powerful synthesis. It is remarkable that though the gravitational theory could not be verified at that time, there was hardly any doubt about its correctness. This is because Newton based his theory on sound scientific reasoning and backed it with mathematics. This made the theory simple and elegant. These qualities are now recognised as essential requirements of a good scientific theory. 1fd01f0c5d36d16a58da557daa55ec1b9c343fa0 Main Page 0 1 39 30 2022-07-02T08:16:29Z SpaceMan 2 /* Quick List */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. ===Quick List=== [[Special:ListUsers]] [[https://astrobase.miraheze.org/wiki/Special:WantedPages|Wanted Pages]] === Miraheze === * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) __INDEX__ __NEWSECTIONLINK__ 0395653c2c3d84e4e22b228af6000f34a48e7812 40 39 2022-07-02T08:17:19Z SpaceMan 2 /* Quick List */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. ===Quick List=== [[Special:ListUsers]] [[Special:WantedPages]] === Miraheze === * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) __INDEX__ __NEWSECTIONLINK__ 97c916f547bcf72172ae6147276d60bb13f4fd29 56 40 2022-07-17T09:25:07Z SpaceMan 2 /* Quick List */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. ===Quick List=== [[Special:All Pages ]] [[Special:ListUsers]] [[Special:WantedPages]] === Miraheze === * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) __INDEX__ __NEWSECTIONLINK__ b38d0bbff7ddb457d30de7c5340c15327f358ef2 57 56 2022-07-17T09:25:36Z SpaceMan 2 /* Quick List */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == Welcome to AstroBase , a knowledge base created especially for Astronomy. Please help us create a Knowledge base for Astronomy. This wiki is hosted in Miraheze and a lot of credit goes to them. ===Quick List=== [[Special:AllPages ]] [[Special:ListUsers]] [[Special:WantedPages]] === Miraheze === * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) __INDEX__ __NEWSECTIONLINK__ 2811d833f7ba2698e712a57ea6d0f8d467892558 60 57 2022-08-27T13:10:53Z SpaceMan 2 /* Welcome to {{SITENAME}}! */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == AstroBase is an online encyclopaedia for astronomy and a wiki. Currently a developing project. ===Quick List=== [[Special:AllPages ]] [[Special:ListUsers]] [[Special:WantedPages]] === Miraheze === * [[mw:Special:MyLanguage/Help:Contents|MediaWiki guide]] (e.g. navigation, editing, deleting pages, blocking users) * [[meta:Special:MyLanguage/FAQ|Miraheze FAQ]] * [[meta:Special:MyLanguage/Request features|Request settings changes on your wiki]]. (Extensions, Skin and Logo/Favicon changes should be done through [[Special:ManageWiki]] on your wiki, see [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] for more information.) * [[meta:Special:MyLanguage/Help center|On our own Miraheze wiki]] * On [[phab:|Phabricator]] * On [https://miraheze.org/discord Discord] * On IRC in #miraheze on irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze webchat]) __INDEX__ __NEWSECTIONLINK__ 5e426a1fa7e148ec0166e9977e84d4acecc3570a 61 60 2022-08-27T14:20:22Z SpaceMan 2 /* Miraheze */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == AstroBase is an online encyclopaedia for astronomy and a wiki. Currently a developing project. ===Quick List=== [[Special:AllPages ]] [[Special:ListUsers]] [[Special:WantedPages]] f04a27b1543292aacbf1264357e019a30d6b5603 62 61 2022-08-27T14:21:29Z SpaceMan 2 /* Quick List */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == AstroBase is an online encyclopaedia for astronomy and a wiki. Currently a developing project. ===Quick List=== [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] 5c60d9048c6e47b8adb8037d2ddfa0e990fb345a 66 62 2022-08-27T14:35:41Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == AstroBase is an online encyclopaedia for astronomy and a wiki. Currently a developing project. ===Quick List=== [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] ===Astronomy Database Portal=== [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 4778c92828aa70e7237ea35f26c04851464f8b86 Star 0 20 41 2022-07-02T08:21:05Z SpaceMan 2 Star wikitext text/x-wiki ===Definition=== A star is an astronomical object comprising a luminous spheroid of [[plasma]] held together by its gravity. The nearest star to [[Earth]] is the [[Sun]]. Many other stars are visible to the naked eye at night, but their immense distances from Earth make them appear as fixed points of [[light]]. The most prominent stars have been categorised into [[constellations]] and [[asterisms]], and many of the brightest stars have proper names. [[Astronomes]] have assembled star catalogues that identify the known stars and provide standardized stellar designations. The observable universe contains an estimated 10²² to 10²⁴ stars. Still, most are invisible to the naked eye from Earth, including all individual stars outside our [[galaxy]], the [[Milky Way]]. A star's life begins with the gravitational([[Gravity]]) collapse of a gaseous [[nebula]] of material composed primarily of [[hydrogen]], along with [[helium]] and trace amounts of heavier elements. Its total mass is the main factor determining its evolution and eventual fate. 51d29fac79f9b36c655eb27f747ca42aa2fc1eb2 43 41 2022-07-02T08:26:54Z SpaceMan 2 /* Definition */ wikitext text/x-wiki ===Definition=== [[[[File:Sunastronomy.jpg|thumb|Sun]]|thumb|alt=Sun|Sun]] A star is an astronomical object comprising a luminous spheroid of [[plasma]] held together by its gravity. The nearest star to [[Earth]] is the [[Sun]]. Many other stars are visible to the naked eye at night, but their immense distances from Earth make them appear as fixed points of [[light]]. The most prominent stars have been categorised into [[constellations]] and [[asterisms]], and many of the brightest stars have proper names. [[Astronomes]] have assembled star catalogues that identify the known stars and provide standardized stellar designations. The observable universe contains an estimated 10²² to 10²⁴ stars. Still, most are invisible to the naked eye from Earth, including all individual stars outside our [[galaxy]], the [[Milky Way]]. A star's life begins with the gravitational([[Gravity]]) collapse of a gaseous [[nebula]] of material composed primarily of [[hydrogen]], along with [[helium]] and trace amounts of heavier elements. Its total mass is the main factor determining its evolution and eventual fate. 95fb79210545de7a6810e7ac32124cba95a7ef41 44 43 2022-07-02T08:31:58Z SpaceMan 2 /* Definition */ wikitext text/x-wiki ===Definition=== [[File:Sunastronomy.jpg|thumb|Sun]] A star is an astronomical object comprising a luminous spheroid of [[plasma]] held together by its gravity. The nearest star to [[Earth]] is the [[Sun]]. Many other stars are visible to the naked eye at night, but their immense distances from Earth make them appear as fixed points of [[light]]. The most prominent stars have been categorised into [[constellations]] and [[asterisms]], and many of the brightest stars have proper names. [[Astronomes]] have assembled star catalogues that identify the known stars and provide standardized stellar designations. The observable universe contains an estimated 10²² to 10²⁴ stars. Still, most are invisible to the naked eye from Earth, including all individual stars outside our [[galaxy]], the [[Milky Way]]. A star's life begins with the gravitational([[Gravity]]) collapse of a gaseous [[nebula]] of material composed primarily of [[hydrogen]], along with [[helium]] and trace amounts of heavier elements. Its total mass is the main factor determining its evolution and eventual fate. d7f24cbb0d64aaf2328c53cea37398b33c97b559 45 44 2022-07-02T08:33:43Z SpaceMan 2 SpaceMan moved page [[Stars]] to [[Star]]: Wrong name wikitext text/x-wiki ===Definition=== [[File:Sunastronomy.jpg|thumb|Sun]] A star is an astronomical object comprising a luminous spheroid of [[plasma]] held together by its gravity. The nearest star to [[Earth]] is the [[Sun]]. Many other stars are visible to the naked eye at night, but their immense distances from Earth make them appear as fixed points of [[light]]. The most prominent stars have been categorised into [[constellations]] and [[asterisms]], and many of the brightest stars have proper names. [[Astronomes]] have assembled star catalogues that identify the known stars and provide standardized stellar designations. The observable universe contains an estimated 10²² to 10²⁴ stars. Still, most are invisible to the naked eye from Earth, including all individual stars outside our [[galaxy]], the [[Milky Way]]. A star's life begins with the gravitational([[Gravity]]) collapse of a gaseous [[nebula]] of material composed primarily of [[hydrogen]], along with [[helium]] and trace amounts of heavier elements. Its total mass is the main factor determining its evolution and eventual fate. d7f24cbb0d64aaf2328c53cea37398b33c97b559 File:Sunastronomy.jpg 6 21 42 2022-07-02T08:24:54Z SpaceMan 2 Uploaded own work with UploadWizard wikitext text/x-wiki =={{int:filedesc}}== {{Information |description={{en|1=Sun in astronomy}} |date=2022-07-02 |source={{own}} |author=[[User:SpaceMan|Astrobase ]] |permission= |other versions= }} =={{int:license-header}}== {{self|cc-by-sa-4.0}} [[Category:Star]] [[Category:Astronomy]] bbc1da1cea1f98aef83543f8b0f83e07975b8275 Stars 0 22 46 2022-07-02T08:33:44Z SpaceMan 2 SpaceMan moved page [[Stars]] to [[Star]]: Wrong name wikitext text/x-wiki #REDIRECT [[Star]] 0d95576f1993901f134db7a5aa54b73e8ffa2754 Grand Unified Theory 0 23 47 2022-07-08T07:43:11Z SpaceMan 2 Created page with " The grand unified theory (GUT) is a theory that remains elusive and complex, but scientists are still working on it. If it is correct, it would explain many observations made in physics and chemistry - from the structure of atoms to the behavior of subatomic particles. While this theory remains undiscovered, there's no doubt that ongoing research will lead to even more revelations about the nature of reality. ===Classic theory=== GUT theory is one of the most popular t..." wikitext text/x-wiki The grand unified theory (GUT) is a theory that remains elusive and complex, but scientists are still working on it. If it is correct, it would explain many observations made in physics and chemistry - from the structure of atoms to the behavior of subatomic particles. While this theory remains undiscovered, there's no doubt that ongoing research will lead to even more revelations about the nature of reality. ===Classic theory=== GUT theory is one of the most popular theories in physics today. It was first proposed by German physicist, [[Max Planck]] in 1900 and has been revised and expanded many times since then. GUT theory is a theory that explains how the [[universe]] works. ===Modern progress=== There is no doubt that the GUT (Gravitation, Unification and Theories) theory is of immense importance. Originally conceived over a hundred years ago, scientists are still uncovering new information about it every day. Despite its age, the GUT theory remains one of the most comprehensive theories in existence today - unifying various fields of physics under one umbrella. Its implications for modern scientific theories cannot be overemphasized. ===Introduction to the Great Theory=== The grand unified theory (GUT), or the great theory, is a theory of quantum mechanics that attempts to explain all the known forces in the universe. It's been controversial since its inception, but it continues to be studied and debated by scientists today. Regardless of whether or not you agree with the GUT, it's an interesting theory worth exploring! Some believe that the GUT is responsible for explaining how particles interact, while others think it has broader implications. For example, some believe that the GUT is responsible for the development of the universe as we know it. The grand unified theory (GUT) is a proposed scientific theory that has been theorized for over 50 years but remains unconfirmed due to its complexity. If it is proven correct, it would greatly affect our understanding of the universe and our place within it. Although there is much speculation surrounding GUT, if it proves true it could have far-reaching consequences for physics and astronomy research. 4b77d75c4052a2e1c4441419d54ffe3213af1877 Astrophysics 0 24 49 48 2022-07-08T17:19:18Z SpaceMan 2 1 revision imported: Astrophysics wikitext text/x-wiki {{short description|Branch of astronomy}} {{About|the use of physics to determine the nature of astronomical objects|the use of physics to determine their positions and motions|Celestial mechanics|the physical study of the largest-scale structures of the universe|Physical cosmology|the journal|Astrophysics (journal)}} {{TopicTOC-Physics}} '''Astrophysics''' is a science that employs the methods and principles of [[physics]] and [[chemistry]] in the study of [[astronomical object]]s and phenomena.<ref>{{cite book |title=Astrophysics in a Nutshell |first=Dan |last=Maoz |date=23 February 2016 |publisher=Princeton University Press |pages=272 |isbn=9781400881178 |url=https://www.google.com/books/edition/Astrophysics_in_a_Nutshell/bmBeCwAAQBAJ?hl=en&gbpv=1&dq=%22astrophysics+is%22&pg=PA1&printsec=frontcover}}</ref><ref>{{cite web | title=astrophysics | publisher=Merriam-Webster, Incorporated | url=http://www.merriam-webster.com/dictionary/astrophysics | access-date=2011-05-22 | archive-url= https://web.archive.org/web/20110610085146/http://www.merriam-webster.com/dictionary/astrophysics| archive-date= 10 June 2011 | url-status= live}}</ref> As one of the founders of the discipline said, Astrophysics "seeks to ascertain the nature of the heavenly bodies, rather than their positions or motions in space–''what'' they are, rather than ''where'' they are."<ref>{{Citation | last = Keeler | first = James E. | author-link = James E. Keeler | title = The Importance of Astrophysical Research and the Relation of Astrophysics to the Other Physical Sciences | journal = The Astrophysical Journal | volume = 6 | issue = 4 | pages = 271–288 | date = November 1897 | bibcode = 1897ApJ.....6..271K |doi = 10.1086/140401 | pmid = 17796068 }}</ref> Among the subjects studied are the [[Sun]], other [[star]]s, [[galaxy|galaxies]], [[extrasolar planet]]s, the [[interstellar medium]] and the [[cosmic microwave background]].<ref name="nasa.gov">{{cite web|url=https://science.nasa.gov/astrophysics/focus-areas/|title=Focus Areas – NASA Science|work=nasa.gov}}</ref><ref>{{cite encyclopedia|url=https://www.britannica.com/EBchecked/topic/40047/astronomy|title=astronomy|encyclopedia=Encyclopædia Britannica}}</ref> Emissions from these objects are examined across all parts of the [[electromagnetic spectrum]], and the properties examined include [[luminosity]], [[density]], [[temperature]], and [[chemistry|chemical]] composition. Because astrophysics is a very broad subject, ''astrophysicists'' apply concepts and methods from many disciplines of physics and chemistry, including [[classical mechanics]], [[electromagnetism]], [[statistical mechanics]], [[thermodynamics]], [[quantum mechanics]], [[theory of relativity|relativity]], [[nuclear physics|nuclear]] and [[particle physics]], and [[atomic, molecular, and optical physics|atomic and molecular physics]]. In practice, modern astronomical research often involves a substantial amount of work in the realms of [[Theoretical physics|theoretical]] and observational physics. Some areas of study for astrophysicists include their attempts to determine the properties of [[dark matter]], [[dark energy]], [[black holes]], and other [[celestial bodies]]; and the [[Cosmogony|origin]] and [[ultimate fate of the universe]].<ref name="nasa.gov"/> Topics also studied by theoretical astrophysicists include [[Formation and evolution of the Solar System|Solar System formation and evolution]]; [[stellar dynamics]] and [[Stellar evolution|evolution]]; [[galaxy formation and evolution]]; [[magnetohydrodynamics]]; [[large-scale structure of the universe|large-scale structure]] of [[matter]] in the universe; origin of [[cosmic ray]]s; [[general relativity]], [[special relativity]], [[quantum cosmology|quantum]] and [[physical cosmology]], including [[string theory|string]] cosmology and [[astroparticle physics]]. ==History== [[Image:NIEdot362.jpg|thumb|left|200px|Early 1900s comparison of elemental, solar, and stellar spectra]] Astronomy is an ancient science, long separated from the study of terrestrial physics. In the [[Aristotle|Aristotelian]] worldview, bodies in the sky appeared to be unchanging [[Celestial spheres|spheres]] whose only motion was uniform motion in a circle, while the earthly world was the realm which underwent [[On Generation and Corruption|growth and decay]] and in which natural motion was in a straight line and ended when the moving object reached its [[Telos|goal]]. Consequently, it was held that the celestial region was made of a fundamentally different kind of matter from that found in the terrestrial sphere; either [[Fire (classical element)|Fire]] as maintained by [[Plato]], or [[Aether (classical element)|Aether]] as maintained by [[Aristotle#Physics|Aristotle]].<ref>{{cite book | last = Lloyd | first = G. E. R. | author-link = G. E. R. Lloyd | title = Aristotle: The Growth and Structure of His Thought | publisher = Cambridge University Press | year = 1968 | location = Cambridge | pages = [https://archive.org/details/aristotlegrowths0000lloy/page/134 134–135] | url =https://archive.org/details/aristotlegrowths0000lloy| url-access = registration | isbn = 978-0-521-09456-6}}</ref><ref>{{cite book | last = Cornford | first = Francis MacDonald | author-link = F. M. Cornford | title = Plato's Cosmology: The ''Timaeus'' of Plato translated, with a running commentary | publisher = Bobbs Merrill Co | date = c. 1957 | orig-year = 1937 | location = Indianapolis | page = 118}}</ref> During the 17th century, natural philosophers such as [[Galileo]],<ref>{{Citation | last = Galilei | first = Galileo | author-link = Galileo Galilei | editor-last = Van Helden | editor-first = Albert | publication-date = 1989 | title = Sidereus Nuncius or The Sidereal Messenger | publisher = University of Chicago Press | location = Chicago | pages = 21, 47 | isbn = 978-0-226-27903-9 | date = 1989-04-15 }}</ref> [[Descartes]],<ref>{{Cite encyclopedia |author=Edward Slowik |title=Descartes' Physics |url=http://plato.stanford.edu/entries/descartes-physics/ |encyclopedia=[[Stanford Encyclopedia of Philosophy]] |date=2013 |orig-year=2005 |access-date=2015-07-18}}</ref> and [[Isaac Newton|Newton]]<ref>{{Citation | last = Westfall | first = Richard S. | author-link = Richard S. Westfall | publication-date = 1980 | title = Never at Rest: A Biography of Isaac Newton | publisher = Cambridge University Press | location = Cambridge | pages = [https://archive.org/details/neveratrestbiogr00west/page/731 731–732] | isbn = 978-0-521-27435-7 | date = 1983-04-29 | url-access = registration | url = https://archive.org/details/neveratrestbiogr00west/page/731 }}</ref> began to maintain that the celestial and terrestrial regions were made of similar kinds of material and were subject to the same [[Physical law|natural laws]].<ref name = Burtt/> Their challenge was that the tools had not yet been invented with which to prove these assertions.<ref>{{Cite journal |author=Ladislav Kvasz |title=Galileo, Descartes, and Newton – Founders of the Language of Physics |url=http://www.physics.sk/aps/pubs/2012/aps-12-06/aps-12-06.pdf |publisher=Institute of Philosophy, [[Academy of Sciences of the Czech Republic]] |date=2013 |access-date=2015-07-18}}</ref> For much of the nineteenth century, astronomical research was focused on the routine work of measuring the positions and computing the motions of astronomical objects.<ref>{{Citation | last = Case | first = Stephen | date = 2015 | title = 'Land-marks of the universe': John Herschel against the background of positional astronomy | journal = Annals of Science | volume = 72 | issue = 4 | pages = 417–434 | doi = 10.1080/00033790.2015.1034588 | pmid = 26221834 | quote = The great majority of astronomers working in the early nineteenth century were not interested in stars as physical objects. Far from being bodies with physical properties to be investigated, the stars were seen as markers measured in order to construct an accurate, detailed and precise background against which solar, lunar and planetary motions could be charted, primarily for terrestrial applications.|bibcode = 2015AnSci..72..417C | doi-access = free }}</ref><ref>{{Citation | last = Donnelly | first = Kevin | date = September 2014 | title = On the boredom of science: positional astronomy in the nineteenth century | journal = The British Journal for the History of Science | volume = 47 | issue = 3 | pages = 479–503 | doi = 10.1017/S0007087413000915 | s2cid = 146382057 | url = https://zenodo.org/record/999531 }}</ref> A new astronomy, soon to be called astrophysics, began to emerge when [[William Hyde Wollaston]] and [[Joseph von Fraunhofer]] independently discovered that, when decomposing the light from the Sun, a multitude of [[Fraunhofer lines|dark lines]] (regions where there was less or no light) were observed in the [[Visible spectrum|spectrum]].<ref>{{cite book | last=Hearnshaw|first=J.B. | title=The analysis of starlight | date=1986 | publisher=Cambridge University Press | location=Cambridge | isbn=978-0-521-39916-6 | pages=23–29}}</ref> By 1860 the physicist, [[Gustav Kirchhoff]], and the chemist, [[Robert Bunsen]], had demonstrated that the [[Absorption spectroscopy#Absorption spectrum|dark lines]] in the solar spectrum corresponded to [[Emission spectrum|bright lines]] in the spectra of known gases, specific lines corresponding to unique [[chemical element]]s.<ref>{{citation | last = Kirchhoff | first = Gustav | author-link = Gustav Kirchhoff |title=Ueber die Fraunhofer'schen Linien | journal=Annalen der Physik | volume=185 |issue=1 | pages=148–150 | date=1860 | bibcode = 1860AnP...185..148K | doi=10.1002/andp.18601850115| url = https://zenodo.org/record/1423666 }}</ref> Kirchhoff deduced that the dark lines in the solar spectrum are caused by [[absorption (optics)|absorption]] by [[chemical elements]] in the Solar atmosphere.<ref>{{citation | last = Kirchhoff | first = Gustav | author-link = Gustav Kirchhoff | title=Ueber das Verhältniss zwischen dem Emissionsvermögen und dem Absorptionsvermögen der Körper für Wärme und Licht |journal=Annalen der Physik |volume=185 | issue=2 | pages=275–301 | date=1860 | bibcode = 1860AnP...185..275K | doi=10.1002/andp.18601850205| url=https://zenodo.org/record/1423668 | doi-access=free }}</ref> In this way it was proved that the chemical elements found in the Sun and stars were also found on Earth. Among those who extended the study of solar and stellar spectra was [[Norman Lockyer]], who in 1868 detected radiant, as well as dark lines in solar spectra. Working with chemist [[Edward Frankland]] to investigate the spectra of elements at various temperatures and pressures, he could not associate a yellow line in the solar spectrum with any known elements. He thus claimed the line represented a new element, which was called [[helium]], after the Greek [[Helios]], the Sun personified.<ref>{{citation | last = Cortie | first = A. L. | title = Sir Norman Lockyer, 1836 – 1920 | journal = The Astrophysical Journal | year = 1921 | volume = 53 | pages = 233–248 | bibcode = 1921ApJ....53..233C | doi=10.1086/142602}}</ref><ref>{{Citation | last = Jensen | first = William B.|author1-link=William B. Jensen | title = Why Helium Ends in "-ium" | journal = Journal of Chemical Education | volume = 81 | issue = 7 | pages = 944–945 | year = 2004 | url = http://www.che.uc.edu/jensen/W.%20B.%20Jensen/Reprints/115.%20Helium.pdf | doi=10.1021/ed081p944 | bibcode = 2004JChEd..81..944J }}</ref> In 1885, [[Edward C. Pickering]] undertook an ambitious program of stellar spectral classification at [[Harvard College Observatory]], in which a team of [[Harvard Computers|woman computers]], notably [[Williamina Fleming]], [[Antonia Maury]], and [[Annie Jump Cannon]], classified the spectra recorded on photographic plates. By 1890, a catalog of over 10,000 stars had been prepared that grouped them into thirteen spectral types. Following Pickering's vision, by 1924 Cannon expanded the [[Henry Draper Catalogue|catalog]] to nine volumes and over a quarter of a million stars, developing the [[Stellar classification#Harvard spectral classification|Harvard Classification Scheme]] which was accepted for worldwide use in 1922.<ref>{{Citation|last1=Hetherington |first1=Norriss S. |last2=McCray |first2=W. Patrick |author2-link=W. Patrick McCray |editor-last=Weart |editor-first=Spencer R. |editor-link=Spencer R. Weart |title=Spectroscopy and the Birth of Astrophysics |publisher=American Institute of Physics, Center for the History of Physics |url=https://www.aip.org/history/cosmology/tools/tools-spectroscopy.htm |access-date=July 19, 2015 |url-status=dead |archive-url=https://web.archive.org/web/20150907133751/https://www.aip.org/history/cosmology/tools/tools-spectroscopy.htm |archive-date=September 7, 2015 }}</ref> In 1895, [[George Ellery Hale]] and [[James E. Keeler]], along with a group of ten associate editors from Europe and the United States,<ref name = Hale1895>{{Citation | last = Hale | first = George Ellery | title = The Astrophysical Journal | author-link = George Ellery Hale | journal = The Astrophysical Journal | volume = 1 | issue = 1 | pages = 80–84 | bibcode = 1895ApJ.....1...80H | doi = 10.1086/140011| year = 1895 }}</ref> established [[The Astrophysical Journal|''The Astrophysical Journal: An International Review of Spectroscopy and Astronomical Physics'']].<ref>{{List journal | journal = The Astrophysical Journal | volume = 1 | issue = 1 }}</ref> It was intended that the journal would fill the gap between journals in astronomy and physics, providing a venue for publication of articles on astronomical applications of the spectroscope; on laboratory research closely allied to astronomical physics, including wavelength determinations of metallic and gaseous spectra and experiments on radiation and absorption; on theories of the Sun, Moon, planets, comets, meteors, and nebulae; and on instrumentation for telescopes and laboratories.<ref name = Hale1895/> Around 1920, following the discovery of the [[Hertzsprung–Russell diagram]] still used as the basis for classifying stars and their evolution, [[Arthur Eddington]] anticipated the discovery and mechanism of [[nuclear fusion]] processes in [[star]]s, in his paper ''The Internal Constitution of the Stars''.<ref name=eddington> {{ Citation | last = Eddington | first = A. S. | author-link = Arthur Eddington | date = October 1920 | title = The Internal Constitution of the Stars | journal = The Scientific Monthly | volume = 11 | issue = 4 | pages = 297–303 | doi = 10.1126/science.52.1341.233 | jstor = 6491 | pmid = 17747682 | bibcode = 1920Sci....52..233E | url = https://zenodo.org/record/1429642 }}</ref><ref name=eddington2>{{cite journal | bibcode = 1916MNRAS..77...16E | title = On the radiative equilibrium of the stars | journal=Monthly Notices of the Royal Astronomical Society | volume=77 | pages=16–35 | last1=Eddington|first1=A. S. | author-link = Arthur Eddington | year=1916 | doi=10.1093/mnras/77.1.16| doi-access=free }}</ref> At that time, the source of stellar energy was a complete mystery; Eddington correctly speculated that the source was [[nuclear fusion|fusion]] of hydrogen into helium, liberating enormous energy according to Einstein's equation ''E = mc<sup>2</sup>''. This was a particularly remarkable development since at that time fusion and thermonuclear energy, and even that stars are largely composed of [[hydrogen]] (see [[metallicity]]), had not yet been discovered.<ref>{{Cite book|title=Fusion|last1=McCracken|editor-last2=Stott|editor-first2=Peter|editor-last=McCracken|editor-first=Garry|last2=Stott|first2=Peter|first1=Garry|url=http://www.sciencedirect.com/science/article/pii/B9780123846563000027|language=en|doi=10.1016/b978-0-12-384656-3.00002-7|pages=13|isbn=978-0-12-384656-3|location=Boston|date=2013-01-01|publisher=Academic Press|quote=Eddington had realized that there would be a mass loss if four hydrogen atoms combined to form a single helium atom. Einstein’s equivalence of mass and energy led directly to the suggestion that this could be the long-sought process that produces the energy in the stars! It was an inspired guess, all the more remarkable because the structure of the nucleus and the mechanisms of these reactions were not fully understood.|edition=Second}}</ref> In 1925 Cecilia Helena Payne (later [[Cecilia Payne-Gaposchkin]]) wrote an influential doctoral dissertation at [[Radcliffe College]], in which she applied ionization theory to stellar atmospheres to relate the spectral classes to the temperature of stars.<ref>{{citation |last=Payne |first=C. H. |year=1925 |title=Stellar Atmospheres; A Contribution to the Observational Study of High Temperature in the Reversing Layers of Stars |type=PhD Thesis |publisher=[[Radcliffe College]] | location = Cambridge, Massachusetts | publication-date = 1925 |bibcode=1925PhDT.........1P }}</ref> Most significantly, she discovered that hydrogen and helium were the principal components of stars. Despite Eddington's suggestion, this discovery was so unexpected that her dissertation readers convinced her to modify the conclusion before publication. However, later research confirmed her discovery.<ref>{{citation | last = Haramundanis | first = Katherine | editor-last = Hockey | editor-first = Thomas | editor2-last = Trimble | editor2-first = Virginia | editor2-link = Virginia Louise Trimble | editor3-last = Williams | editor3-first = Thomas R. | title = Biographical Encyclopedia of Astronomers | chapter = Payne-Gaposchkin [Payne], Cecilia Helena | access-date = July 19, 2015 |year=2007 | chapter-url=https://books.google.com/books?id=t-BF1CHkc50C | pages=876–878 | publisher = Springer | location = New York | isbn = 978-0-387-30400-7 }}</ref> By the end of the 20th century, studies of astronomical spectra had expanded to cover wavelengths extending from radio waves through optical, x-ray, and gamma wavelengths.<ref>{{cite conference |mode=cs2 |last1=Biermann |first1=Peter L. |last2=Falcke |first2=Heino |author2-link=Heino Falcke |editor-last=Panvini |editor-first=Robert S. |editor2-last=Weiler |editor2-first=Thomas J. |date=1998 |book-title=Fundamental particles and interactions: Frontiers in contemporary physics an international lecture and workshop series. AIP Conference Proceedings |title=Frontiers of Astrophysics: Workshop Summary |volume=423 |publisher=American Institute of Physics |pages=236–248 |isbn=1-56396-725-1 |bibcode=1998AIPC..423..236B |doi=10.1063/1.55085|arxiv=astro-ph/9711066 }}</ref> In the 21st century, it further expanded to include observations based on [[gravitational waves]]. ==Observational astrophysics== [[Image:N 63A- Chandra and Hubble - Heic0507f.tif|thumb|right|200px|Supernova remnant LMC N 63A imaged in x-ray (blue), optical (green) and radio (red) wavelengths. The X-ray glow is from material heated to about ten million degrees Celsius by a shock wave generated by the supernova explosion.]] [[Observational astronomy]] is a division of the astronomical science that is concerned with recording and interpreting data, in contrast with [[theoretical astrophysics]], which is mainly concerned with finding out the measurable implications of physical [[model (abstract)|models]]. It is the practice of observing [[celestial object]]s by using [[telescope]]s and other astronomical apparatus. The majority of astrophysical observations are made using the [[electromagnetic spectrum]]. * [[Radio astronomy]] studies radiation with a [[wavelength]] greater than a few millimeters. Example areas of study are [[radio waves]], usually emitted by cold objects such as [[interstellar gas]] and dust clouds; the cosmic microwave background radiation which is the [[redshift]]ed light from the [[Big Bang]]; [[pulsar]]s, which were first detected at [[microwave]] frequencies. The study of these waves requires very large [[radio telescope]]s. * [[Infrared astronomy]] studies radiation with a wavelength that is too long to be visible to the naked eye but is shorter than radio waves. Infrared observations are usually made with telescopes similar to the familiar [[optical]] telescopes. Objects colder than stars (such as planets) are normally studied at infrared frequencies. * [[Optical astronomy]] was the earliest kind of astronomy. Telescopes paired with a [[charge-coupled device]] or [[spectroscope]]s are the most common instruments used. The Earth's [[atmosphere]] interferes somewhat with optical observations, so [[adaptive optics]] and [[space telescope]]s are used to obtain the highest possible image quality. In this wavelength range, stars are highly visible, and many chemical spectra can be observed to study the chemical composition of stars, galaxies, and [[nebula]]e. * [[Ultraviolet]], [[X-ray astronomy|X-ray]] and [[gamma ray astronomy]] study very energetic processes such as [[binary pulsar]]s, [[black hole]]s, [[magnetar]]s, and many others. These kinds of radiation do not penetrate the Earth's atmosphere well. There are two methods in use to observe this part of the electromagnetic spectrum—[[space-based telescope]]s and ground-based [[imaging air Cherenkov telescope]]s (IACT). Examples of [[Observatory|Observatories]] of the first type are [[RXTE]], the [[Chandra X-ray Observatory]] and the [[Compton Gamma Ray Observatory]]. Examples of IACTs are the [[High Energy Stereoscopic System]] (H.E.S.S.) and the [[MAGIC (telescope)|MAGIC]] telescope. Other than electromagnetic radiation, few things may be observed from the Earth that originate from great distances. A few [[gravitational wave]] observatories have been constructed, but gravitational waves are extremely difficult to detect. [[Neutrino]] observatories have also been built, primarily to study our Sun. Cosmic rays consisting of very high-energy particles can be observed hitting the Earth's atmosphere. Observations can also vary in their time scale. Most optical observations take minutes to hours, so phenomena that change faster than this cannot readily be observed. However, historical data on some objects is available, spanning [[century|centuries]] or [[millennia]]. On the other hand, radio observations may look at events on a millisecond timescale ([[millisecond pulsar]]s) or combine years of data ([[Rotation-powered pulsar|pulsar deceleration]] studies). The information obtained from these different timescales is very different. The study of our very own Sun has a special place in observational astrophysics. Due to the tremendous distance of all other stars, the Sun can be observed in a kind of detail unparalleled by any other star. Our understanding of our own Sun serves as a guide to our understanding of other stars. The topic of how stars change, or stellar evolution, is often modeled by placing the varieties of star types in their respective positions on the [[Hertzsprung–Russell diagram]], which can be viewed as representing the state of a stellar object, from birth to destruction. ==Theoretical astrophysics== {{see also|Theoretical astronomy}} Theoretical astrophysicists use a wide variety of tools which include [[mathematical model|analytical models]] (for example, [[polytrope]]s to approximate the behaviors of a star) and [[computation]]al [[Numerical analysis|numerical simulations]]. Each has some advantages. Analytical models of a process are generally better for giving insight into the heart of what is going on. Numerical models can reveal the existence of phenomena and effects that would otherwise not be seen.<ref>{{Citation |first=H. |last=Roth |title=A Slowly Contracting or Expanding Fluid Sphere and its Stability |journal=[[Physical Review]] |volume=39 |issue=3 |pages=525–529 |year=1932 |doi=10.1103/PhysRev.39.525 |bibcode = 1932PhRv...39..525R }}</ref><ref>{{Citation |first=A.S. |last=Eddington |title=Internal Constitution of the Stars |journal=Science |location=New York |publisher=Cambridge University Press |orig-year=1926 |year=1988 |volume=52 |issue=1341 |pages=233–240 |doi=10.1126/science.52.1341.233 |isbn=978-0-521-33708-3 |pmid=17747682 |bibcode=1920Sci....52..233E |url=https://zenodo.org/record/1429642 }}</ref> Theorists in astrophysics endeavor to create theoretical models and figure out the observational consequences of those models. This helps allow observers to look for data that can refute a model or help in choosing between several alternate or conflicting models. Theorists also try to generate or modify models to take into account new data. In the case of an inconsistency, the general tendency is to try to make minimal modifications to the model to fit the data. In some cases, a large amount of inconsistent data over time may lead to total abandonment of a model. Topics studied by theoretical astrophysicists include stellar dynamics and evolution; galaxy formation and evolution; magnetohydrodynamics; large-scale structure of matter in the universe; origin of cosmic rays; general relativity and physical cosmology, including [[string theory|string]] cosmology and astroparticle physics. Astrophysical relativity serves as a tool to gauge the properties of large-scale structures for which gravitation plays a significant role in physical phenomena investigated and as the basis for [[black hole]] (''astro'')physics and the study of [[gravitational waves]]. Some widely accepted and studied theories and models in astrophysics, now included in the [[Lambda-CDM model]], are the [[Big Bang]], [[cosmic inflation]], dark matter, dark energy and fundamental theories of physics. == Popularization == The roots of astrophysics can be found in the seventeenth century emergence of a unified physics, in which the same laws applied to the celestial and terrestrial realms.<ref name = Burtt>{{Citation | last = Burtt | first = Edwin Arthur | author-link = Edwin Arthur Burtt | publication-date = 2003 | orig-year = First published 1924 | title = The Metaphysical Foundations of Modern Science | edition = second revised | publisher = Dover Publications | location = Mineola, NY | pages = 30, 41, 241–2 | isbn = 978-0-486-42551-1 | url = https://books.google.com/books?id=G9WBMa1Rz_kC | year = 2003 }}</ref> There were scientists who were qualified in both physics and astronomy who laid the firm foundation for the current science of astrophysics. In modern times, students continue to be drawn to astrophysics due to its popularization by the [[Royal Astronomical Society]] and notable [[Science education|educators]] such as prominent professors [[Lawrence Krauss]], [[Subrahmanyan Chandrasekhar]], [[Stephen Hawking]], [[Hubert Reeves]], [[Carl Sagan]], [[Neil deGrasse Tyson]] and [[Patrick Moore]]. The efforts of the early, late, and present scientists continue to attract young people to study the history and science of astrophysics.<ref>{{Cite web |author=D. Mark Manley |title=Famous Astronomers and Astrophysicists |url=http://cnr2.kent.edu/~manley/astronomers.html |publisher=[[Kent State University]] |date=2012 |access-date=2015-07-17}}</ref><ref>{{Cite web |author=The science.ca team |title=Hubert Reeves – Astronomy, Astrophysics and Space Science |url=http://www.science.ca/scientists/scientistprofile.php?pID=213 |publisher=GCS Research Society |date=2015 |access-date=2015-07-17}}</ref><ref>{{Cite web |title=Neil deGrasse Tyson |url=http://www.haydenplanetarium.org/tyson/ |publisher=[[Hayden Planetarium]] |date=2015 |access-date=2015-07-17}}</ref> ==See also== {{cols|colwidth=21em}} * [[Astrochemistry]] * [[List of astronomical observatories|Astronomical observatories]] * [[Astronomical spectroscopy]] * [[Astroparticle physics]] * [[Gravitational-wave astronomy]] * [[Hertzsprung–Russell diagram]] * [[High-energy astronomy]] * [[List of important publications in physics#Astrophysics|Important publications in astrophysics]] * [[List of astronomers]] (includes astrophysicists) * [[Neutrino astronomy]] (future prospects) * [[Timeline of gravitational physics and relativity]] * [[Timeline of knowledge about galaxies, clusters of galaxies, and large-scale structure]] * [[Timeline of white dwarfs, neutron stars, and supernovae]] {{colend}} ==References== {{Reflist}} ==Further reading== * {{Citation | last = Longair | first = Malcolm S. | author-link = Malcolm S. Longair | title = The Cosmic Century: A History of Astrophysics and Cosmology | place = Cambridge | publisher = Cambridge University Press | year = 2006 | isbn = 978-0-521-47436-8 | url-access = registration | url = https://archive.org/details/cosmiccenturyhis0000long }} * [http://www.scholarpedia.org/article/Encyclopedia:Astrophysics Astrophysics] [[Scholarpedia]] Expert articles ==External links== {{Wikibooks|Astrophysics}} {{Library resources box|onlinebooks=yes}} * [http://www.aanda.org/ ''Astronomy and Astrophysics'', a European Journal] * [http://iopscience.iop.org/0004-637X/ ''Astrophysical Journal''] * [http://www.aip.org/history/cosmology/index.htm Cosmic Journey: A History of Scientific Cosmology] from the American Institute of Physics * [http://www.worldscinet.com/ijmpd/ijmpd.shtml ''International Journal of Modern Physics D''] from [[World Scientific]] * [http://www.scienceresourceworld.com/publications/journals/astronomy_journals.html List and directory of peer-reviewed Astronomy / Astrophysics Journals] * [http://www.astro.ucla.edu/~wright/cosmolog.htm Ned Wright's Cosmology Tutorial, UCLA] {{Physics-footer}} {{Astronomy subfields}} {{Astronomy navbox}} {{Portal bar|Physics|Astronomy|Stars|Spaceflight|Outer space|Solar System}} {{Authority control}} [[Category:Astrophysics| ]] [[Category:Astronomical sub-disciplines]] bd2c54352b5f33382b25fe37da4e112ea4e9afdc 50 49 2022-07-08T17:20:09Z SpaceMan 2 /* External links */ wikitext text/x-wiki {{short description|Branch of astronomy}} {{About|the use of physics to determine the nature of astronomical objects|the use of physics to determine their positions and motions|Celestial mechanics|the physical study of the largest-scale structures of the universe|Physical cosmology|the journal|Astrophysics (journal)}} {{TopicTOC-Physics}} '''Astrophysics''' is a science that employs the methods and principles of [[physics]] and [[chemistry]] in the study of [[astronomical object]]s and phenomena.<ref>{{cite book |title=Astrophysics in a Nutshell |first=Dan |last=Maoz |date=23 February 2016 |publisher=Princeton University Press |pages=272 |isbn=9781400881178 |url=https://www.google.com/books/edition/Astrophysics_in_a_Nutshell/bmBeCwAAQBAJ?hl=en&gbpv=1&dq=%22astrophysics+is%22&pg=PA1&printsec=frontcover}}</ref><ref>{{cite web | title=astrophysics | publisher=Merriam-Webster, Incorporated | url=http://www.merriam-webster.com/dictionary/astrophysics | access-date=2011-05-22 | archive-url= https://web.archive.org/web/20110610085146/http://www.merriam-webster.com/dictionary/astrophysics| archive-date= 10 June 2011 | url-status= live}}</ref> As one of the founders of the discipline said, Astrophysics "seeks to ascertain the nature of the heavenly bodies, rather than their positions or motions in space–''what'' they are, rather than ''where'' they are."<ref>{{Citation | last = Keeler | first = James E. | author-link = James E. Keeler | title = The Importance of Astrophysical Research and the Relation of Astrophysics to the Other Physical Sciences | journal = The Astrophysical Journal | volume = 6 | issue = 4 | pages = 271–288 | date = November 1897 | bibcode = 1897ApJ.....6..271K |doi = 10.1086/140401 | pmid = 17796068 }}</ref> Among the subjects studied are the [[Sun]], other [[star]]s, [[galaxy|galaxies]], [[extrasolar planet]]s, the [[interstellar medium]] and the [[cosmic microwave background]].<ref name="nasa.gov">{{cite web|url=https://science.nasa.gov/astrophysics/focus-areas/|title=Focus Areas – NASA Science|work=nasa.gov}}</ref><ref>{{cite encyclopedia|url=https://www.britannica.com/EBchecked/topic/40047/astronomy|title=astronomy|encyclopedia=Encyclopædia Britannica}}</ref> Emissions from these objects are examined across all parts of the [[electromagnetic spectrum]], and the properties examined include [[luminosity]], [[density]], [[temperature]], and [[chemistry|chemical]] composition. Because astrophysics is a very broad subject, ''astrophysicists'' apply concepts and methods from many disciplines of physics and chemistry, including [[classical mechanics]], [[electromagnetism]], [[statistical mechanics]], [[thermodynamics]], [[quantum mechanics]], [[theory of relativity|relativity]], [[nuclear physics|nuclear]] and [[particle physics]], and [[atomic, molecular, and optical physics|atomic and molecular physics]]. In practice, modern astronomical research often involves a substantial amount of work in the realms of [[Theoretical physics|theoretical]] and observational physics. Some areas of study for astrophysicists include their attempts to determine the properties of [[dark matter]], [[dark energy]], [[black holes]], and other [[celestial bodies]]; and the [[Cosmogony|origin]] and [[ultimate fate of the universe]].<ref name="nasa.gov"/> Topics also studied by theoretical astrophysicists include [[Formation and evolution of the Solar System|Solar System formation and evolution]]; [[stellar dynamics]] and [[Stellar evolution|evolution]]; [[galaxy formation and evolution]]; [[magnetohydrodynamics]]; [[large-scale structure of the universe|large-scale structure]] of [[matter]] in the universe; origin of [[cosmic ray]]s; [[general relativity]], [[special relativity]], [[quantum cosmology|quantum]] and [[physical cosmology]], including [[string theory|string]] cosmology and [[astroparticle physics]]. ==History== [[Image:NIEdot362.jpg|thumb|left|200px|Early 1900s comparison of elemental, solar, and stellar spectra]] Astronomy is an ancient science, long separated from the study of terrestrial physics. In the [[Aristotle|Aristotelian]] worldview, bodies in the sky appeared to be unchanging [[Celestial spheres|spheres]] whose only motion was uniform motion in a circle, while the earthly world was the realm which underwent [[On Generation and Corruption|growth and decay]] and in which natural motion was in a straight line and ended when the moving object reached its [[Telos|goal]]. Consequently, it was held that the celestial region was made of a fundamentally different kind of matter from that found in the terrestrial sphere; either [[Fire (classical element)|Fire]] as maintained by [[Plato]], or [[Aether (classical element)|Aether]] as maintained by [[Aristotle#Physics|Aristotle]].<ref>{{cite book | last = Lloyd | first = G. E. R. | author-link = G. E. R. Lloyd | title = Aristotle: The Growth and Structure of His Thought | publisher = Cambridge University Press | year = 1968 | location = Cambridge | pages = [https://archive.org/details/aristotlegrowths0000lloy/page/134 134–135] | url =https://archive.org/details/aristotlegrowths0000lloy| url-access = registration | isbn = 978-0-521-09456-6}}</ref><ref>{{cite book | last = Cornford | first = Francis MacDonald | author-link = F. M. Cornford | title = Plato's Cosmology: The ''Timaeus'' of Plato translated, with a running commentary | publisher = Bobbs Merrill Co | date = c. 1957 | orig-year = 1937 | location = Indianapolis | page = 118}}</ref> During the 17th century, natural philosophers such as [[Galileo]],<ref>{{Citation | last = Galilei | first = Galileo | author-link = Galileo Galilei | editor-last = Van Helden | editor-first = Albert | publication-date = 1989 | title = Sidereus Nuncius or The Sidereal Messenger | publisher = University of Chicago Press | location = Chicago | pages = 21, 47 | isbn = 978-0-226-27903-9 | date = 1989-04-15 }}</ref> [[Descartes]],<ref>{{Cite encyclopedia |author=Edward Slowik |title=Descartes' Physics |url=http://plato.stanford.edu/entries/descartes-physics/ |encyclopedia=[[Stanford Encyclopedia of Philosophy]] |date=2013 |orig-year=2005 |access-date=2015-07-18}}</ref> and [[Isaac Newton|Newton]]<ref>{{Citation | last = Westfall | first = Richard S. | author-link = Richard S. Westfall | publication-date = 1980 | title = Never at Rest: A Biography of Isaac Newton | publisher = Cambridge University Press | location = Cambridge | pages = [https://archive.org/details/neveratrestbiogr00west/page/731 731–732] | isbn = 978-0-521-27435-7 | date = 1983-04-29 | url-access = registration | url = https://archive.org/details/neveratrestbiogr00west/page/731 }}</ref> began to maintain that the celestial and terrestrial regions were made of similar kinds of material and were subject to the same [[Physical law|natural laws]].<ref name = Burtt/> Their challenge was that the tools had not yet been invented with which to prove these assertions.<ref>{{Cite journal |author=Ladislav Kvasz |title=Galileo, Descartes, and Newton – Founders of the Language of Physics |url=http://www.physics.sk/aps/pubs/2012/aps-12-06/aps-12-06.pdf |publisher=Institute of Philosophy, [[Academy of Sciences of the Czech Republic]] |date=2013 |access-date=2015-07-18}}</ref> For much of the nineteenth century, astronomical research was focused on the routine work of measuring the positions and computing the motions of astronomical objects.<ref>{{Citation | last = Case | first = Stephen | date = 2015 | title = 'Land-marks of the universe': John Herschel against the background of positional astronomy | journal = Annals of Science | volume = 72 | issue = 4 | pages = 417–434 | doi = 10.1080/00033790.2015.1034588 | pmid = 26221834 | quote = The great majority of astronomers working in the early nineteenth century were not interested in stars as physical objects. Far from being bodies with physical properties to be investigated, the stars were seen as markers measured in order to construct an accurate, detailed and precise background against which solar, lunar and planetary motions could be charted, primarily for terrestrial applications.|bibcode = 2015AnSci..72..417C | doi-access = free }}</ref><ref>{{Citation | last = Donnelly | first = Kevin | date = September 2014 | title = On the boredom of science: positional astronomy in the nineteenth century | journal = The British Journal for the History of Science | volume = 47 | issue = 3 | pages = 479–503 | doi = 10.1017/S0007087413000915 | s2cid = 146382057 | url = https://zenodo.org/record/999531 }}</ref> A new astronomy, soon to be called astrophysics, began to emerge when [[William Hyde Wollaston]] and [[Joseph von Fraunhofer]] independently discovered that, when decomposing the light from the Sun, a multitude of [[Fraunhofer lines|dark lines]] (regions where there was less or no light) were observed in the [[Visible spectrum|spectrum]].<ref>{{cite book | last=Hearnshaw|first=J.B. | title=The analysis of starlight | date=1986 | publisher=Cambridge University Press | location=Cambridge | isbn=978-0-521-39916-6 | pages=23–29}}</ref> By 1860 the physicist, [[Gustav Kirchhoff]], and the chemist, [[Robert Bunsen]], had demonstrated that the [[Absorption spectroscopy#Absorption spectrum|dark lines]] in the solar spectrum corresponded to [[Emission spectrum|bright lines]] in the spectra of known gases, specific lines corresponding to unique [[chemical element]]s.<ref>{{citation | last = Kirchhoff | first = Gustav | author-link = Gustav Kirchhoff |title=Ueber die Fraunhofer'schen Linien | journal=Annalen der Physik | volume=185 |issue=1 | pages=148–150 | date=1860 | bibcode = 1860AnP...185..148K | doi=10.1002/andp.18601850115| url = https://zenodo.org/record/1423666 }}</ref> Kirchhoff deduced that the dark lines in the solar spectrum are caused by [[absorption (optics)|absorption]] by [[chemical elements]] in the Solar atmosphere.<ref>{{citation | last = Kirchhoff | first = Gustav | author-link = Gustav Kirchhoff | title=Ueber das Verhältniss zwischen dem Emissionsvermögen und dem Absorptionsvermögen der Körper für Wärme und Licht |journal=Annalen der Physik |volume=185 | issue=2 | pages=275–301 | date=1860 | bibcode = 1860AnP...185..275K | doi=10.1002/andp.18601850205| url=https://zenodo.org/record/1423668 | doi-access=free }}</ref> In this way it was proved that the chemical elements found in the Sun and stars were also found on Earth. Among those who extended the study of solar and stellar spectra was [[Norman Lockyer]], who in 1868 detected radiant, as well as dark lines in solar spectra. Working with chemist [[Edward Frankland]] to investigate the spectra of elements at various temperatures and pressures, he could not associate a yellow line in the solar spectrum with any known elements. He thus claimed the line represented a new element, which was called [[helium]], after the Greek [[Helios]], the Sun personified.<ref>{{citation | last = Cortie | first = A. L. | title = Sir Norman Lockyer, 1836 – 1920 | journal = The Astrophysical Journal | year = 1921 | volume = 53 | pages = 233–248 | bibcode = 1921ApJ....53..233C | doi=10.1086/142602}}</ref><ref>{{Citation | last = Jensen | first = William B.|author1-link=William B. Jensen | title = Why Helium Ends in "-ium" | journal = Journal of Chemical Education | volume = 81 | issue = 7 | pages = 944–945 | year = 2004 | url = http://www.che.uc.edu/jensen/W.%20B.%20Jensen/Reprints/115.%20Helium.pdf | doi=10.1021/ed081p944 | bibcode = 2004JChEd..81..944J }}</ref> In 1885, [[Edward C. Pickering]] undertook an ambitious program of stellar spectral classification at [[Harvard College Observatory]], in which a team of [[Harvard Computers|woman computers]], notably [[Williamina Fleming]], [[Antonia Maury]], and [[Annie Jump Cannon]], classified the spectra recorded on photographic plates. By 1890, a catalog of over 10,000 stars had been prepared that grouped them into thirteen spectral types. Following Pickering's vision, by 1924 Cannon expanded the [[Henry Draper Catalogue|catalog]] to nine volumes and over a quarter of a million stars, developing the [[Stellar classification#Harvard spectral classification|Harvard Classification Scheme]] which was accepted for worldwide use in 1922.<ref>{{Citation|last1=Hetherington |first1=Norriss S. |last2=McCray |first2=W. Patrick |author2-link=W. Patrick McCray |editor-last=Weart |editor-first=Spencer R. |editor-link=Spencer R. Weart |title=Spectroscopy and the Birth of Astrophysics |publisher=American Institute of Physics, Center for the History of Physics |url=https://www.aip.org/history/cosmology/tools/tools-spectroscopy.htm |access-date=July 19, 2015 |url-status=dead |archive-url=https://web.archive.org/web/20150907133751/https://www.aip.org/history/cosmology/tools/tools-spectroscopy.htm |archive-date=September 7, 2015 }}</ref> In 1895, [[George Ellery Hale]] and [[James E. Keeler]], along with a group of ten associate editors from Europe and the United States,<ref name = Hale1895>{{Citation | last = Hale | first = George Ellery | title = The Astrophysical Journal | author-link = George Ellery Hale | journal = The Astrophysical Journal | volume = 1 | issue = 1 | pages = 80–84 | bibcode = 1895ApJ.....1...80H | doi = 10.1086/140011| year = 1895 }}</ref> established [[The Astrophysical Journal|''The Astrophysical Journal: An International Review of Spectroscopy and Astronomical Physics'']].<ref>{{List journal | journal = The Astrophysical Journal | volume = 1 | issue = 1 }}</ref> It was intended that the journal would fill the gap between journals in astronomy and physics, providing a venue for publication of articles on astronomical applications of the spectroscope; on laboratory research closely allied to astronomical physics, including wavelength determinations of metallic and gaseous spectra and experiments on radiation and absorption; on theories of the Sun, Moon, planets, comets, meteors, and nebulae; and on instrumentation for telescopes and laboratories.<ref name = Hale1895/> Around 1920, following the discovery of the [[Hertzsprung–Russell diagram]] still used as the basis for classifying stars and their evolution, [[Arthur Eddington]] anticipated the discovery and mechanism of [[nuclear fusion]] processes in [[star]]s, in his paper ''The Internal Constitution of the Stars''.<ref name=eddington> {{ Citation | last = Eddington | first = A. S. | author-link = Arthur Eddington | date = October 1920 | title = The Internal Constitution of the Stars | journal = The Scientific Monthly | volume = 11 | issue = 4 | pages = 297–303 | doi = 10.1126/science.52.1341.233 | jstor = 6491 | pmid = 17747682 | bibcode = 1920Sci....52..233E | url = https://zenodo.org/record/1429642 }}</ref><ref name=eddington2>{{cite journal | bibcode = 1916MNRAS..77...16E | title = On the radiative equilibrium of the stars | journal=Monthly Notices of the Royal Astronomical Society | volume=77 | pages=16–35 | last1=Eddington|first1=A. S. | author-link = Arthur Eddington | year=1916 | doi=10.1093/mnras/77.1.16| doi-access=free }}</ref> At that time, the source of stellar energy was a complete mystery; Eddington correctly speculated that the source was [[nuclear fusion|fusion]] of hydrogen into helium, liberating enormous energy according to Einstein's equation ''E = mc<sup>2</sup>''. This was a particularly remarkable development since at that time fusion and thermonuclear energy, and even that stars are largely composed of [[hydrogen]] (see [[metallicity]]), had not yet been discovered.<ref>{{Cite book|title=Fusion|last1=McCracken|editor-last2=Stott|editor-first2=Peter|editor-last=McCracken|editor-first=Garry|last2=Stott|first2=Peter|first1=Garry|url=http://www.sciencedirect.com/science/article/pii/B9780123846563000027|language=en|doi=10.1016/b978-0-12-384656-3.00002-7|pages=13|isbn=978-0-12-384656-3|location=Boston|date=2013-01-01|publisher=Academic Press|quote=Eddington had realized that there would be a mass loss if four hydrogen atoms combined to form a single helium atom. Einstein’s equivalence of mass and energy led directly to the suggestion that this could be the long-sought process that produces the energy in the stars! It was an inspired guess, all the more remarkable because the structure of the nucleus and the mechanisms of these reactions were not fully understood.|edition=Second}}</ref> In 1925 Cecilia Helena Payne (later [[Cecilia Payne-Gaposchkin]]) wrote an influential doctoral dissertation at [[Radcliffe College]], in which she applied ionization theory to stellar atmospheres to relate the spectral classes to the temperature of stars.<ref>{{citation |last=Payne |first=C. H. |year=1925 |title=Stellar Atmospheres; A Contribution to the Observational Study of High Temperature in the Reversing Layers of Stars |type=PhD Thesis |publisher=[[Radcliffe College]] | location = Cambridge, Massachusetts | publication-date = 1925 |bibcode=1925PhDT.........1P }}</ref> Most significantly, she discovered that hydrogen and helium were the principal components of stars. Despite Eddington's suggestion, this discovery was so unexpected that her dissertation readers convinced her to modify the conclusion before publication. However, later research confirmed her discovery.<ref>{{citation | last = Haramundanis | first = Katherine | editor-last = Hockey | editor-first = Thomas | editor2-last = Trimble | editor2-first = Virginia | editor2-link = Virginia Louise Trimble | editor3-last = Williams | editor3-first = Thomas R. | title = Biographical Encyclopedia of Astronomers | chapter = Payne-Gaposchkin [Payne], Cecilia Helena | access-date = July 19, 2015 |year=2007 | chapter-url=https://books.google.com/books?id=t-BF1CHkc50C | pages=876–878 | publisher = Springer | location = New York | isbn = 978-0-387-30400-7 }}</ref> By the end of the 20th century, studies of astronomical spectra had expanded to cover wavelengths extending from radio waves through optical, x-ray, and gamma wavelengths.<ref>{{cite conference |mode=cs2 |last1=Biermann |first1=Peter L. |last2=Falcke |first2=Heino |author2-link=Heino Falcke |editor-last=Panvini |editor-first=Robert S. |editor2-last=Weiler |editor2-first=Thomas J. |date=1998 |book-title=Fundamental particles and interactions: Frontiers in contemporary physics an international lecture and workshop series. AIP Conference Proceedings |title=Frontiers of Astrophysics: Workshop Summary |volume=423 |publisher=American Institute of Physics |pages=236–248 |isbn=1-56396-725-1 |bibcode=1998AIPC..423..236B |doi=10.1063/1.55085|arxiv=astro-ph/9711066 }}</ref> In the 21st century, it further expanded to include observations based on [[gravitational waves]]. ==Observational astrophysics== [[Image:N 63A- Chandra and Hubble - Heic0507f.tif|thumb|right|200px|Supernova remnant LMC N 63A imaged in x-ray (blue), optical (green) and radio (red) wavelengths. The X-ray glow is from material heated to about ten million degrees Celsius by a shock wave generated by the supernova explosion.]] [[Observational astronomy]] is a division of the astronomical science that is concerned with recording and interpreting data, in contrast with [[theoretical astrophysics]], which is mainly concerned with finding out the measurable implications of physical [[model (abstract)|models]]. It is the practice of observing [[celestial object]]s by using [[telescope]]s and other astronomical apparatus. The majority of astrophysical observations are made using the [[electromagnetic spectrum]]. * [[Radio astronomy]] studies radiation with a [[wavelength]] greater than a few millimeters. Example areas of study are [[radio waves]], usually emitted by cold objects such as [[interstellar gas]] and dust clouds; the cosmic microwave background radiation which is the [[redshift]]ed light from the [[Big Bang]]; [[pulsar]]s, which were first detected at [[microwave]] frequencies. The study of these waves requires very large [[radio telescope]]s. * [[Infrared astronomy]] studies radiation with a wavelength that is too long to be visible to the naked eye but is shorter than radio waves. Infrared observations are usually made with telescopes similar to the familiar [[optical]] telescopes. Objects colder than stars (such as planets) are normally studied at infrared frequencies. * [[Optical astronomy]] was the earliest kind of astronomy. Telescopes paired with a [[charge-coupled device]] or [[spectroscope]]s are the most common instruments used. The Earth's [[atmosphere]] interferes somewhat with optical observations, so [[adaptive optics]] and [[space telescope]]s are used to obtain the highest possible image quality. In this wavelength range, stars are highly visible, and many chemical spectra can be observed to study the chemical composition of stars, galaxies, and [[nebula]]e. * [[Ultraviolet]], [[X-ray astronomy|X-ray]] and [[gamma ray astronomy]] study very energetic processes such as [[binary pulsar]]s, [[black hole]]s, [[magnetar]]s, and many others. These kinds of radiation do not penetrate the Earth's atmosphere well. There are two methods in use to observe this part of the electromagnetic spectrum—[[space-based telescope]]s and ground-based [[imaging air Cherenkov telescope]]s (IACT). Examples of [[Observatory|Observatories]] of the first type are [[RXTE]], the [[Chandra X-ray Observatory]] and the [[Compton Gamma Ray Observatory]]. Examples of IACTs are the [[High Energy Stereoscopic System]] (H.E.S.S.) and the [[MAGIC (telescope)|MAGIC]] telescope. Other than electromagnetic radiation, few things may be observed from the Earth that originate from great distances. A few [[gravitational wave]] observatories have been constructed, but gravitational waves are extremely difficult to detect. [[Neutrino]] observatories have also been built, primarily to study our Sun. Cosmic rays consisting of very high-energy particles can be observed hitting the Earth's atmosphere. Observations can also vary in their time scale. Most optical observations take minutes to hours, so phenomena that change faster than this cannot readily be observed. However, historical data on some objects is available, spanning [[century|centuries]] or [[millennia]]. On the other hand, radio observations may look at events on a millisecond timescale ([[millisecond pulsar]]s) or combine years of data ([[Rotation-powered pulsar|pulsar deceleration]] studies). The information obtained from these different timescales is very different. The study of our very own Sun has a special place in observational astrophysics. Due to the tremendous distance of all other stars, the Sun can be observed in a kind of detail unparalleled by any other star. Our understanding of our own Sun serves as a guide to our understanding of other stars. The topic of how stars change, or stellar evolution, is often modeled by placing the varieties of star types in their respective positions on the [[Hertzsprung–Russell diagram]], which can be viewed as representing the state of a stellar object, from birth to destruction. ==Theoretical astrophysics== {{see also|Theoretical astronomy}} Theoretical astrophysicists use a wide variety of tools which include [[mathematical model|analytical models]] (for example, [[polytrope]]s to approximate the behaviors of a star) and [[computation]]al [[Numerical analysis|numerical simulations]]. Each has some advantages. Analytical models of a process are generally better for giving insight into the heart of what is going on. Numerical models can reveal the existence of phenomena and effects that would otherwise not be seen.<ref>{{Citation |first=H. |last=Roth |title=A Slowly Contracting or Expanding Fluid Sphere and its Stability |journal=[[Physical Review]] |volume=39 |issue=3 |pages=525–529 |year=1932 |doi=10.1103/PhysRev.39.525 |bibcode = 1932PhRv...39..525R }}</ref><ref>{{Citation |first=A.S. |last=Eddington |title=Internal Constitution of the Stars |journal=Science |location=New York |publisher=Cambridge University Press |orig-year=1926 |year=1988 |volume=52 |issue=1341 |pages=233–240 |doi=10.1126/science.52.1341.233 |isbn=978-0-521-33708-3 |pmid=17747682 |bibcode=1920Sci....52..233E |url=https://zenodo.org/record/1429642 }}</ref> Theorists in astrophysics endeavor to create theoretical models and figure out the observational consequences of those models. This helps allow observers to look for data that can refute a model or help in choosing between several alternate or conflicting models. Theorists also try to generate or modify models to take into account new data. In the case of an inconsistency, the general tendency is to try to make minimal modifications to the model to fit the data. In some cases, a large amount of inconsistent data over time may lead to total abandonment of a model. Topics studied by theoretical astrophysicists include stellar dynamics and evolution; galaxy formation and evolution; magnetohydrodynamics; large-scale structure of matter in the universe; origin of cosmic rays; general relativity and physical cosmology, including [[string theory|string]] cosmology and astroparticle physics. Astrophysical relativity serves as a tool to gauge the properties of large-scale structures for which gravitation plays a significant role in physical phenomena investigated and as the basis for [[black hole]] (''astro'')physics and the study of [[gravitational waves]]. Some widely accepted and studied theories and models in astrophysics, now included in the [[Lambda-CDM model]], are the [[Big Bang]], [[cosmic inflation]], dark matter, dark energy and fundamental theories of physics. == Popularization == The roots of astrophysics can be found in the seventeenth century emergence of a unified physics, in which the same laws applied to the celestial and terrestrial realms.<ref name = Burtt>{{Citation | last = Burtt | first = Edwin Arthur | author-link = Edwin Arthur Burtt | publication-date = 2003 | orig-year = First published 1924 | title = The Metaphysical Foundations of Modern Science | edition = second revised | publisher = Dover Publications | location = Mineola, NY | pages = 30, 41, 241–2 | isbn = 978-0-486-42551-1 | url = https://books.google.com/books?id=G9WBMa1Rz_kC | year = 2003 }}</ref> There were scientists who were qualified in both physics and astronomy who laid the firm foundation for the current science of astrophysics. In modern times, students continue to be drawn to astrophysics due to its popularization by the [[Royal Astronomical Society]] and notable [[Science education|educators]] such as prominent professors [[Lawrence Krauss]], [[Subrahmanyan Chandrasekhar]], [[Stephen Hawking]], [[Hubert Reeves]], [[Carl Sagan]], [[Neil deGrasse Tyson]] and [[Patrick Moore]]. The efforts of the early, late, and present scientists continue to attract young people to study the history and science of astrophysics.<ref>{{Cite web |author=D. Mark Manley |title=Famous Astronomers and Astrophysicists |url=http://cnr2.kent.edu/~manley/astronomers.html |publisher=[[Kent State University]] |date=2012 |access-date=2015-07-17}}</ref><ref>{{Cite web |author=The science.ca team |title=Hubert Reeves – Astronomy, Astrophysics and Space Science |url=http://www.science.ca/scientists/scientistprofile.php?pID=213 |publisher=GCS Research Society |date=2015 |access-date=2015-07-17}}</ref><ref>{{Cite web |title=Neil deGrasse Tyson |url=http://www.haydenplanetarium.org/tyson/ |publisher=[[Hayden Planetarium]] |date=2015 |access-date=2015-07-17}}</ref> ==See also== {{cols|colwidth=21em}} * [[Astrochemistry]] * [[List of astronomical observatories|Astronomical observatories]] * [[Astronomical spectroscopy]] * [[Astroparticle physics]] * [[Gravitational-wave astronomy]] * [[Hertzsprung–Russell diagram]] * [[High-energy astronomy]] * [[List of important publications in physics#Astrophysics|Important publications in astrophysics]] * [[List of astronomers]] (includes astrophysicists) * [[Neutrino astronomy]] (future prospects) * [[Timeline of gravitational physics and relativity]] * [[Timeline of knowledge about galaxies, clusters of galaxies, and large-scale structure]] * [[Timeline of white dwarfs, neutron stars, and supernovae]] {{colend}} ==References== {{Reflist}} ==Further reading== * {{Citation | last = Longair | first = Malcolm S. | author-link = Malcolm S. Longair | title = The Cosmic Century: A History of Astrophysics and Cosmology | place = Cambridge | publisher = Cambridge University Press | year = 2006 | isbn = 978-0-521-47436-8 | url-access = registration | url = https://archive.org/details/cosmiccenturyhis0000long }} * [http://www.scholarpedia.org/article/Encyclopedia:Astrophysics Astrophysics] [[Scholarpedia]] Expert articles ==External links== {{Wikibooks|Astrophysics}} {{Library resources box|onlinebooks=yes}} * [http://www.aanda.org/ ''Astronomy and Astrophysics'', a European Journal] * [http://iopscience.iop.org/0004-637X/ ''Astrophysical Journal''] * [http://www.aip.org/history/cosmology/index.htm Cosmic Journey: A History of Scientific Cosmology] from the American Institute of Physics * [http://www.worldscinet.com/ijmpd/ijmpd.shtml ''International Journal of Modern Physics D''] from [[World Scientific]] * [http://www.scienceresourceworld.com/publications/journals/astronomy_journals.html List and directory of peer-reviewed Astronomy / Astrophysics Journals] * [http://www.astro.ucla.edu/~wright/cosmolog.htm Ned Wright's Cosmology Tutorial, UCLA] e5badca507ad3ccdb40c5cd0bc4e6e251b56be53 51 50 2022-07-08T17:21:09Z SpaceMan 2 Protected "[[Astrophysics]]" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) wikitext text/x-wiki {{short description|Branch of astronomy}} {{About|the use of physics to determine the nature of astronomical objects|the use of physics to determine their positions and motions|Celestial mechanics|the physical study of the largest-scale structures of the universe|Physical cosmology|the journal|Astrophysics (journal)}} {{TopicTOC-Physics}} '''Astrophysics''' is a science that employs the methods and principles of [[physics]] and [[chemistry]] in the study of [[astronomical object]]s and phenomena.<ref>{{cite book |title=Astrophysics in a Nutshell |first=Dan |last=Maoz |date=23 February 2016 |publisher=Princeton University Press |pages=272 |isbn=9781400881178 |url=https://www.google.com/books/edition/Astrophysics_in_a_Nutshell/bmBeCwAAQBAJ?hl=en&gbpv=1&dq=%22astrophysics+is%22&pg=PA1&printsec=frontcover}}</ref><ref>{{cite web | title=astrophysics | publisher=Merriam-Webster, Incorporated | url=http://www.merriam-webster.com/dictionary/astrophysics | access-date=2011-05-22 | archive-url= https://web.archive.org/web/20110610085146/http://www.merriam-webster.com/dictionary/astrophysics| archive-date= 10 June 2011 | url-status= live}}</ref> As one of the founders of the discipline said, Astrophysics "seeks to ascertain the nature of the heavenly bodies, rather than their positions or motions in space–''what'' they are, rather than ''where'' they are."<ref>{{Citation | last = Keeler | first = James E. | author-link = James E. Keeler | title = The Importance of Astrophysical Research and the Relation of Astrophysics to the Other Physical Sciences | journal = The Astrophysical Journal | volume = 6 | issue = 4 | pages = 271–288 | date = November 1897 | bibcode = 1897ApJ.....6..271K |doi = 10.1086/140401 | pmid = 17796068 }}</ref> Among the subjects studied are the [[Sun]], other [[star]]s, [[galaxy|galaxies]], [[extrasolar planet]]s, the [[interstellar medium]] and the [[cosmic microwave background]].<ref name="nasa.gov">{{cite web|url=https://science.nasa.gov/astrophysics/focus-areas/|title=Focus Areas – NASA Science|work=nasa.gov}}</ref><ref>{{cite encyclopedia|url=https://www.britannica.com/EBchecked/topic/40047/astronomy|title=astronomy|encyclopedia=Encyclopædia Britannica}}</ref> Emissions from these objects are examined across all parts of the [[electromagnetic spectrum]], and the properties examined include [[luminosity]], [[density]], [[temperature]], and [[chemistry|chemical]] composition. Because astrophysics is a very broad subject, ''astrophysicists'' apply concepts and methods from many disciplines of physics and chemistry, including [[classical mechanics]], [[electromagnetism]], [[statistical mechanics]], [[thermodynamics]], [[quantum mechanics]], [[theory of relativity|relativity]], [[nuclear physics|nuclear]] and [[particle physics]], and [[atomic, molecular, and optical physics|atomic and molecular physics]]. In practice, modern astronomical research often involves a substantial amount of work in the realms of [[Theoretical physics|theoretical]] and observational physics. Some areas of study for astrophysicists include their attempts to determine the properties of [[dark matter]], [[dark energy]], [[black holes]], and other [[celestial bodies]]; and the [[Cosmogony|origin]] and [[ultimate fate of the universe]].<ref name="nasa.gov"/> Topics also studied by theoretical astrophysicists include [[Formation and evolution of the Solar System|Solar System formation and evolution]]; [[stellar dynamics]] and [[Stellar evolution|evolution]]; [[galaxy formation and evolution]]; [[magnetohydrodynamics]]; [[large-scale structure of the universe|large-scale structure]] of [[matter]] in the universe; origin of [[cosmic ray]]s; [[general relativity]], [[special relativity]], [[quantum cosmology|quantum]] and [[physical cosmology]], including [[string theory|string]] cosmology and [[astroparticle physics]]. ==History== [[Image:NIEdot362.jpg|thumb|left|200px|Early 1900s comparison of elemental, solar, and stellar spectra]] Astronomy is an ancient science, long separated from the study of terrestrial physics. In the [[Aristotle|Aristotelian]] worldview, bodies in the sky appeared to be unchanging [[Celestial spheres|spheres]] whose only motion was uniform motion in a circle, while the earthly world was the realm which underwent [[On Generation and Corruption|growth and decay]] and in which natural motion was in a straight line and ended when the moving object reached its [[Telos|goal]]. Consequently, it was held that the celestial region was made of a fundamentally different kind of matter from that found in the terrestrial sphere; either [[Fire (classical element)|Fire]] as maintained by [[Plato]], or [[Aether (classical element)|Aether]] as maintained by [[Aristotle#Physics|Aristotle]].<ref>{{cite book | last = Lloyd | first = G. E. R. | author-link = G. E. R. Lloyd | title = Aristotle: The Growth and Structure of His Thought | publisher = Cambridge University Press | year = 1968 | location = Cambridge | pages = [https://archive.org/details/aristotlegrowths0000lloy/page/134 134–135] | url =https://archive.org/details/aristotlegrowths0000lloy| url-access = registration | isbn = 978-0-521-09456-6}}</ref><ref>{{cite book | last = Cornford | first = Francis MacDonald | author-link = F. M. Cornford | title = Plato's Cosmology: The ''Timaeus'' of Plato translated, with a running commentary | publisher = Bobbs Merrill Co | date = c. 1957 | orig-year = 1937 | location = Indianapolis | page = 118}}</ref> During the 17th century, natural philosophers such as [[Galileo]],<ref>{{Citation | last = Galilei | first = Galileo | author-link = Galileo Galilei | editor-last = Van Helden | editor-first = Albert | publication-date = 1989 | title = Sidereus Nuncius or The Sidereal Messenger | publisher = University of Chicago Press | location = Chicago | pages = 21, 47 | isbn = 978-0-226-27903-9 | date = 1989-04-15 }}</ref> [[Descartes]],<ref>{{Cite encyclopedia |author=Edward Slowik |title=Descartes' Physics |url=http://plato.stanford.edu/entries/descartes-physics/ |encyclopedia=[[Stanford Encyclopedia of Philosophy]] |date=2013 |orig-year=2005 |access-date=2015-07-18}}</ref> and [[Isaac Newton|Newton]]<ref>{{Citation | last = Westfall | first = Richard S. | author-link = Richard S. Westfall | publication-date = 1980 | title = Never at Rest: A Biography of Isaac Newton | publisher = Cambridge University Press | location = Cambridge | pages = [https://archive.org/details/neveratrestbiogr00west/page/731 731–732] | isbn = 978-0-521-27435-7 | date = 1983-04-29 | url-access = registration | url = https://archive.org/details/neveratrestbiogr00west/page/731 }}</ref> began to maintain that the celestial and terrestrial regions were made of similar kinds of material and were subject to the same [[Physical law|natural laws]].<ref name = Burtt/> Their challenge was that the tools had not yet been invented with which to prove these assertions.<ref>{{Cite journal |author=Ladislav Kvasz |title=Galileo, Descartes, and Newton – Founders of the Language of Physics |url=http://www.physics.sk/aps/pubs/2012/aps-12-06/aps-12-06.pdf |publisher=Institute of Philosophy, [[Academy of Sciences of the Czech Republic]] |date=2013 |access-date=2015-07-18}}</ref> For much of the nineteenth century, astronomical research was focused on the routine work of measuring the positions and computing the motions of astronomical objects.<ref>{{Citation | last = Case | first = Stephen | date = 2015 | title = 'Land-marks of the universe': John Herschel against the background of positional astronomy | journal = Annals of Science | volume = 72 | issue = 4 | pages = 417–434 | doi = 10.1080/00033790.2015.1034588 | pmid = 26221834 | quote = The great majority of astronomers working in the early nineteenth century were not interested in stars as physical objects. Far from being bodies with physical properties to be investigated, the stars were seen as markers measured in order to construct an accurate, detailed and precise background against which solar, lunar and planetary motions could be charted, primarily for terrestrial applications.|bibcode = 2015AnSci..72..417C | doi-access = free }}</ref><ref>{{Citation | last = Donnelly | first = Kevin | date = September 2014 | title = On the boredom of science: positional astronomy in the nineteenth century | journal = The British Journal for the History of Science | volume = 47 | issue = 3 | pages = 479–503 | doi = 10.1017/S0007087413000915 | s2cid = 146382057 | url = https://zenodo.org/record/999531 }}</ref> A new astronomy, soon to be called astrophysics, began to emerge when [[William Hyde Wollaston]] and [[Joseph von Fraunhofer]] independently discovered that, when decomposing the light from the Sun, a multitude of [[Fraunhofer lines|dark lines]] (regions where there was less or no light) were observed in the [[Visible spectrum|spectrum]].<ref>{{cite book | last=Hearnshaw|first=J.B. | title=The analysis of starlight | date=1986 | publisher=Cambridge University Press | location=Cambridge | isbn=978-0-521-39916-6 | pages=23–29}}</ref> By 1860 the physicist, [[Gustav Kirchhoff]], and the chemist, [[Robert Bunsen]], had demonstrated that the [[Absorption spectroscopy#Absorption spectrum|dark lines]] in the solar spectrum corresponded to [[Emission spectrum|bright lines]] in the spectra of known gases, specific lines corresponding to unique [[chemical element]]s.<ref>{{citation | last = Kirchhoff | first = Gustav | author-link = Gustav Kirchhoff |title=Ueber die Fraunhofer'schen Linien | journal=Annalen der Physik | volume=185 |issue=1 | pages=148–150 | date=1860 | bibcode = 1860AnP...185..148K | doi=10.1002/andp.18601850115| url = https://zenodo.org/record/1423666 }}</ref> Kirchhoff deduced that the dark lines in the solar spectrum are caused by [[absorption (optics)|absorption]] by [[chemical elements]] in the Solar atmosphere.<ref>{{citation | last = Kirchhoff | first = Gustav | author-link = Gustav Kirchhoff | title=Ueber das Verhältniss zwischen dem Emissionsvermögen und dem Absorptionsvermögen der Körper für Wärme und Licht |journal=Annalen der Physik |volume=185 | issue=2 | pages=275–301 | date=1860 | bibcode = 1860AnP...185..275K | doi=10.1002/andp.18601850205| url=https://zenodo.org/record/1423668 | doi-access=free }}</ref> In this way it was proved that the chemical elements found in the Sun and stars were also found on Earth. Among those who extended the study of solar and stellar spectra was [[Norman Lockyer]], who in 1868 detected radiant, as well as dark lines in solar spectra. Working with chemist [[Edward Frankland]] to investigate the spectra of elements at various temperatures and pressures, he could not associate a yellow line in the solar spectrum with any known elements. He thus claimed the line represented a new element, which was called [[helium]], after the Greek [[Helios]], the Sun personified.<ref>{{citation | last = Cortie | first = A. L. | title = Sir Norman Lockyer, 1836 – 1920 | journal = The Astrophysical Journal | year = 1921 | volume = 53 | pages = 233–248 | bibcode = 1921ApJ....53..233C | doi=10.1086/142602}}</ref><ref>{{Citation | last = Jensen | first = William B.|author1-link=William B. Jensen | title = Why Helium Ends in "-ium" | journal = Journal of Chemical Education | volume = 81 | issue = 7 | pages = 944–945 | year = 2004 | url = http://www.che.uc.edu/jensen/W.%20B.%20Jensen/Reprints/115.%20Helium.pdf | doi=10.1021/ed081p944 | bibcode = 2004JChEd..81..944J }}</ref> In 1885, [[Edward C. Pickering]] undertook an ambitious program of stellar spectral classification at [[Harvard College Observatory]], in which a team of [[Harvard Computers|woman computers]], notably [[Williamina Fleming]], [[Antonia Maury]], and [[Annie Jump Cannon]], classified the spectra recorded on photographic plates. By 1890, a catalog of over 10,000 stars had been prepared that grouped them into thirteen spectral types. Following Pickering's vision, by 1924 Cannon expanded the [[Henry Draper Catalogue|catalog]] to nine volumes and over a quarter of a million stars, developing the [[Stellar classification#Harvard spectral classification|Harvard Classification Scheme]] which was accepted for worldwide use in 1922.<ref>{{Citation|last1=Hetherington |first1=Norriss S. |last2=McCray |first2=W. Patrick |author2-link=W. Patrick McCray |editor-last=Weart |editor-first=Spencer R. |editor-link=Spencer R. Weart |title=Spectroscopy and the Birth of Astrophysics |publisher=American Institute of Physics, Center for the History of Physics |url=https://www.aip.org/history/cosmology/tools/tools-spectroscopy.htm |access-date=July 19, 2015 |url-status=dead |archive-url=https://web.archive.org/web/20150907133751/https://www.aip.org/history/cosmology/tools/tools-spectroscopy.htm |archive-date=September 7, 2015 }}</ref> In 1895, [[George Ellery Hale]] and [[James E. Keeler]], along with a group of ten associate editors from Europe and the United States,<ref name = Hale1895>{{Citation | last = Hale | first = George Ellery | title = The Astrophysical Journal | author-link = George Ellery Hale | journal = The Astrophysical Journal | volume = 1 | issue = 1 | pages = 80–84 | bibcode = 1895ApJ.....1...80H | doi = 10.1086/140011| year = 1895 }}</ref> established [[The Astrophysical Journal|''The Astrophysical Journal: An International Review of Spectroscopy and Astronomical Physics'']].<ref>{{List journal | journal = The Astrophysical Journal | volume = 1 | issue = 1 }}</ref> It was intended that the journal would fill the gap between journals in astronomy and physics, providing a venue for publication of articles on astronomical applications of the spectroscope; on laboratory research closely allied to astronomical physics, including wavelength determinations of metallic and gaseous spectra and experiments on radiation and absorption; on theories of the Sun, Moon, planets, comets, meteors, and nebulae; and on instrumentation for telescopes and laboratories.<ref name = Hale1895/> Around 1920, following the discovery of the [[Hertzsprung–Russell diagram]] still used as the basis for classifying stars and their evolution, [[Arthur Eddington]] anticipated the discovery and mechanism of [[nuclear fusion]] processes in [[star]]s, in his paper ''The Internal Constitution of the Stars''.<ref name=eddington> {{ Citation | last = Eddington | first = A. S. | author-link = Arthur Eddington | date = October 1920 | title = The Internal Constitution of the Stars | journal = The Scientific Monthly | volume = 11 | issue = 4 | pages = 297–303 | doi = 10.1126/science.52.1341.233 | jstor = 6491 | pmid = 17747682 | bibcode = 1920Sci....52..233E | url = https://zenodo.org/record/1429642 }}</ref><ref name=eddington2>{{cite journal | bibcode = 1916MNRAS..77...16E | title = On the radiative equilibrium of the stars | journal=Monthly Notices of the Royal Astronomical Society | volume=77 | pages=16–35 | last1=Eddington|first1=A. S. | author-link = Arthur Eddington | year=1916 | doi=10.1093/mnras/77.1.16| doi-access=free }}</ref> At that time, the source of stellar energy was a complete mystery; Eddington correctly speculated that the source was [[nuclear fusion|fusion]] of hydrogen into helium, liberating enormous energy according to Einstein's equation ''E = mc<sup>2</sup>''. This was a particularly remarkable development since at that time fusion and thermonuclear energy, and even that stars are largely composed of [[hydrogen]] (see [[metallicity]]), had not yet been discovered.<ref>{{Cite book|title=Fusion|last1=McCracken|editor-last2=Stott|editor-first2=Peter|editor-last=McCracken|editor-first=Garry|last2=Stott|first2=Peter|first1=Garry|url=http://www.sciencedirect.com/science/article/pii/B9780123846563000027|language=en|doi=10.1016/b978-0-12-384656-3.00002-7|pages=13|isbn=978-0-12-384656-3|location=Boston|date=2013-01-01|publisher=Academic Press|quote=Eddington had realized that there would be a mass loss if four hydrogen atoms combined to form a single helium atom. Einstein’s equivalence of mass and energy led directly to the suggestion that this could be the long-sought process that produces the energy in the stars! It was an inspired guess, all the more remarkable because the structure of the nucleus and the mechanisms of these reactions were not fully understood.|edition=Second}}</ref> In 1925 Cecilia Helena Payne (later [[Cecilia Payne-Gaposchkin]]) wrote an influential doctoral dissertation at [[Radcliffe College]], in which she applied ionization theory to stellar atmospheres to relate the spectral classes to the temperature of stars.<ref>{{citation |last=Payne |first=C. H. |year=1925 |title=Stellar Atmospheres; A Contribution to the Observational Study of High Temperature in the Reversing Layers of Stars |type=PhD Thesis |publisher=[[Radcliffe College]] | location = Cambridge, Massachusetts | publication-date = 1925 |bibcode=1925PhDT.........1P }}</ref> Most significantly, she discovered that hydrogen and helium were the principal components of stars. Despite Eddington's suggestion, this discovery was so unexpected that her dissertation readers convinced her to modify the conclusion before publication. However, later research confirmed her discovery.<ref>{{citation | last = Haramundanis | first = Katherine | editor-last = Hockey | editor-first = Thomas | editor2-last = Trimble | editor2-first = Virginia | editor2-link = Virginia Louise Trimble | editor3-last = Williams | editor3-first = Thomas R. | title = Biographical Encyclopedia of Astronomers | chapter = Payne-Gaposchkin [Payne], Cecilia Helena | access-date = July 19, 2015 |year=2007 | chapter-url=https://books.google.com/books?id=t-BF1CHkc50C | pages=876–878 | publisher = Springer | location = New York | isbn = 978-0-387-30400-7 }}</ref> By the end of the 20th century, studies of astronomical spectra had expanded to cover wavelengths extending from radio waves through optical, x-ray, and gamma wavelengths.<ref>{{cite conference |mode=cs2 |last1=Biermann |first1=Peter L. |last2=Falcke |first2=Heino |author2-link=Heino Falcke |editor-last=Panvini |editor-first=Robert S. |editor2-last=Weiler |editor2-first=Thomas J. |date=1998 |book-title=Fundamental particles and interactions: Frontiers in contemporary physics an international lecture and workshop series. AIP Conference Proceedings |title=Frontiers of Astrophysics: Workshop Summary |volume=423 |publisher=American Institute of Physics |pages=236–248 |isbn=1-56396-725-1 |bibcode=1998AIPC..423..236B |doi=10.1063/1.55085|arxiv=astro-ph/9711066 }}</ref> In the 21st century, it further expanded to include observations based on [[gravitational waves]]. ==Observational astrophysics== [[Image:N 63A- Chandra and Hubble - Heic0507f.tif|thumb|right|200px|Supernova remnant LMC N 63A imaged in x-ray (blue), optical (green) and radio (red) wavelengths. The X-ray glow is from material heated to about ten million degrees Celsius by a shock wave generated by the supernova explosion.]] [[Observational astronomy]] is a division of the astronomical science that is concerned with recording and interpreting data, in contrast with [[theoretical astrophysics]], which is mainly concerned with finding out the measurable implications of physical [[model (abstract)|models]]. It is the practice of observing [[celestial object]]s by using [[telescope]]s and other astronomical apparatus. The majority of astrophysical observations are made using the [[electromagnetic spectrum]]. * [[Radio astronomy]] studies radiation with a [[wavelength]] greater than a few millimeters. Example areas of study are [[radio waves]], usually emitted by cold objects such as [[interstellar gas]] and dust clouds; the cosmic microwave background radiation which is the [[redshift]]ed light from the [[Big Bang]]; [[pulsar]]s, which were first detected at [[microwave]] frequencies. The study of these waves requires very large [[radio telescope]]s. * [[Infrared astronomy]] studies radiation with a wavelength that is too long to be visible to the naked eye but is shorter than radio waves. Infrared observations are usually made with telescopes similar to the familiar [[optical]] telescopes. Objects colder than stars (such as planets) are normally studied at infrared frequencies. * [[Optical astronomy]] was the earliest kind of astronomy. Telescopes paired with a [[charge-coupled device]] or [[spectroscope]]s are the most common instruments used. The Earth's [[atmosphere]] interferes somewhat with optical observations, so [[adaptive optics]] and [[space telescope]]s are used to obtain the highest possible image quality. In this wavelength range, stars are highly visible, and many chemical spectra can be observed to study the chemical composition of stars, galaxies, and [[nebula]]e. * [[Ultraviolet]], [[X-ray astronomy|X-ray]] and [[gamma ray astronomy]] study very energetic processes such as [[binary pulsar]]s, [[black hole]]s, [[magnetar]]s, and many others. These kinds of radiation do not penetrate the Earth's atmosphere well. There are two methods in use to observe this part of the electromagnetic spectrum—[[space-based telescope]]s and ground-based [[imaging air Cherenkov telescope]]s (IACT). Examples of [[Observatory|Observatories]] of the first type are [[RXTE]], the [[Chandra X-ray Observatory]] and the [[Compton Gamma Ray Observatory]]. Examples of IACTs are the [[High Energy Stereoscopic System]] (H.E.S.S.) and the [[MAGIC (telescope)|MAGIC]] telescope. Other than electromagnetic radiation, few things may be observed from the Earth that originate from great distances. A few [[gravitational wave]] observatories have been constructed, but gravitational waves are extremely difficult to detect. [[Neutrino]] observatories have also been built, primarily to study our Sun. Cosmic rays consisting of very high-energy particles can be observed hitting the Earth's atmosphere. Observations can also vary in their time scale. Most optical observations take minutes to hours, so phenomena that change faster than this cannot readily be observed. However, historical data on some objects is available, spanning [[century|centuries]] or [[millennia]]. On the other hand, radio observations may look at events on a millisecond timescale ([[millisecond pulsar]]s) or combine years of data ([[Rotation-powered pulsar|pulsar deceleration]] studies). The information obtained from these different timescales is very different. The study of our very own Sun has a special place in observational astrophysics. Due to the tremendous distance of all other stars, the Sun can be observed in a kind of detail unparalleled by any other star. Our understanding of our own Sun serves as a guide to our understanding of other stars. The topic of how stars change, or stellar evolution, is often modeled by placing the varieties of star types in their respective positions on the [[Hertzsprung–Russell diagram]], which can be viewed as representing the state of a stellar object, from birth to destruction. ==Theoretical astrophysics== {{see also|Theoretical astronomy}} Theoretical astrophysicists use a wide variety of tools which include [[mathematical model|analytical models]] (for example, [[polytrope]]s to approximate the behaviors of a star) and [[computation]]al [[Numerical analysis|numerical simulations]]. Each has some advantages. Analytical models of a process are generally better for giving insight into the heart of what is going on. Numerical models can reveal the existence of phenomena and effects that would otherwise not be seen.<ref>{{Citation |first=H. |last=Roth |title=A Slowly Contracting or Expanding Fluid Sphere and its Stability |journal=[[Physical Review]] |volume=39 |issue=3 |pages=525–529 |year=1932 |doi=10.1103/PhysRev.39.525 |bibcode = 1932PhRv...39..525R }}</ref><ref>{{Citation |first=A.S. |last=Eddington |title=Internal Constitution of the Stars |journal=Science |location=New York |publisher=Cambridge University Press |orig-year=1926 |year=1988 |volume=52 |issue=1341 |pages=233–240 |doi=10.1126/science.52.1341.233 |isbn=978-0-521-33708-3 |pmid=17747682 |bibcode=1920Sci....52..233E |url=https://zenodo.org/record/1429642 }}</ref> Theorists in astrophysics endeavor to create theoretical models and figure out the observational consequences of those models. This helps allow observers to look for data that can refute a model or help in choosing between several alternate or conflicting models. Theorists also try to generate or modify models to take into account new data. In the case of an inconsistency, the general tendency is to try to make minimal modifications to the model to fit the data. In some cases, a large amount of inconsistent data over time may lead to total abandonment of a model. Topics studied by theoretical astrophysicists include stellar dynamics and evolution; galaxy formation and evolution; magnetohydrodynamics; large-scale structure of matter in the universe; origin of cosmic rays; general relativity and physical cosmology, including [[string theory|string]] cosmology and astroparticle physics. Astrophysical relativity serves as a tool to gauge the properties of large-scale structures for which gravitation plays a significant role in physical phenomena investigated and as the basis for [[black hole]] (''astro'')physics and the study of [[gravitational waves]]. Some widely accepted and studied theories and models in astrophysics, now included in the [[Lambda-CDM model]], are the [[Big Bang]], [[cosmic inflation]], dark matter, dark energy and fundamental theories of physics. == Popularization == The roots of astrophysics can be found in the seventeenth century emergence of a unified physics, in which the same laws applied to the celestial and terrestrial realms.<ref name = Burtt>{{Citation | last = Burtt | first = Edwin Arthur | author-link = Edwin Arthur Burtt | publication-date = 2003 | orig-year = First published 1924 | title = The Metaphysical Foundations of Modern Science | edition = second revised | publisher = Dover Publications | location = Mineola, NY | pages = 30, 41, 241–2 | isbn = 978-0-486-42551-1 | url = https://books.google.com/books?id=G9WBMa1Rz_kC | year = 2003 }}</ref> There were scientists who were qualified in both physics and astronomy who laid the firm foundation for the current science of astrophysics. In modern times, students continue to be drawn to astrophysics due to its popularization by the [[Royal Astronomical Society]] and notable [[Science education|educators]] such as prominent professors [[Lawrence Krauss]], [[Subrahmanyan Chandrasekhar]], [[Stephen Hawking]], [[Hubert Reeves]], [[Carl Sagan]], [[Neil deGrasse Tyson]] and [[Patrick Moore]]. The efforts of the early, late, and present scientists continue to attract young people to study the history and science of astrophysics.<ref>{{Cite web |author=D. Mark Manley |title=Famous Astronomers and Astrophysicists |url=http://cnr2.kent.edu/~manley/astronomers.html |publisher=[[Kent State University]] |date=2012 |access-date=2015-07-17}}</ref><ref>{{Cite web |author=The science.ca team |title=Hubert Reeves – Astronomy, Astrophysics and Space Science |url=http://www.science.ca/scientists/scientistprofile.php?pID=213 |publisher=GCS Research Society |date=2015 |access-date=2015-07-17}}</ref><ref>{{Cite web |title=Neil deGrasse Tyson |url=http://www.haydenplanetarium.org/tyson/ |publisher=[[Hayden Planetarium]] |date=2015 |access-date=2015-07-17}}</ref> ==See also== {{cols|colwidth=21em}} * [[Astrochemistry]] * [[List of astronomical observatories|Astronomical observatories]] * [[Astronomical spectroscopy]] * [[Astroparticle physics]] * [[Gravitational-wave astronomy]] * [[Hertzsprung–Russell diagram]] * [[High-energy astronomy]] * [[List of important publications in physics#Astrophysics|Important publications in astrophysics]] * [[List of astronomers]] (includes astrophysicists) * [[Neutrino astronomy]] (future prospects) * [[Timeline of gravitational physics and relativity]] * [[Timeline of knowledge about galaxies, clusters of galaxies, and large-scale structure]] * [[Timeline of white dwarfs, neutron stars, and supernovae]] {{colend}} ==References== {{Reflist}} ==Further reading== * {{Citation | last = Longair | first = Malcolm S. | author-link = Malcolm S. Longair | title = The Cosmic Century: A History of Astrophysics and Cosmology | place = Cambridge | publisher = Cambridge University Press | year = 2006 | isbn = 978-0-521-47436-8 | url-access = registration | url = https://archive.org/details/cosmiccenturyhis0000long }} * [http://www.scholarpedia.org/article/Encyclopedia:Astrophysics Astrophysics] [[Scholarpedia]] Expert articles ==External links== {{Wikibooks|Astrophysics}} {{Library resources box|onlinebooks=yes}} * [http://www.aanda.org/ ''Astronomy and Astrophysics'', a European Journal] * [http://iopscience.iop.org/0004-637X/ ''Astrophysical Journal''] * [http://www.aip.org/history/cosmology/index.htm Cosmic Journey: A History of Scientific Cosmology] from the American Institute of Physics * [http://www.worldscinet.com/ijmpd/ijmpd.shtml ''International Journal of Modern Physics D''] from [[World Scientific]] * [http://www.scienceresourceworld.com/publications/journals/astronomy_journals.html List and directory of peer-reviewed Astronomy / Astrophysics Journals] * [http://www.astro.ucla.edu/~wright/cosmolog.htm Ned Wright's Cosmology Tutorial, UCLA] e5badca507ad3ccdb40c5cd0bc4e6e251b56be53 Template:Round 10 126 267 2022-07-09T01:53:46Z Canopus >Neveselbert 0 safesubst wikitext text/x-wiki <includeonly>{{safesubst<noinclude/>:#iferror:{{#expr:{{{2|0}}}}} | {{main other|[[Category:Pages with bad rounding precision]]}}{{hid|Bad rounding here}}<!-- -->{{safesubst<noinclude/>:#invoke:Math|precision_format| {{{1}}} | 1-{{order of magnitude|{{{1}}}}} }}| {{safesubst<noinclude/>:#invoke:Math|precision_format| {{{1}}} | {{{2|0}}}}}}}</includeonly><noinclude> {{documentation}} </noinclude> 9c2874586b74824fe1beb6830b56eabe7ad936ce Template:Sky 10 140 295 2022-07-14T20:04:15Z Canopus >TheDJ 0 avoid <p> wikitext text/x-wiki <noinclude></noinclude><includeonly>{{#ifeq:{{{display|}}}|inline|<span class="sky-coordinates-inline plainlinks nourlexpansion">[[File:Jupiter and moon.png|20px|link=|Sky map]] [http://www.wikisky.org/?ra={{#expr:{{trim|{{{1}}}}}+{{trim|{{{2}}}}}/60+{{trim|{{{3}}}}}/3600}}&de={{#expr:{{trim|{{{4|+}}}}}{{trim|{{{5}}}}}+{{trim|{{{4|+}}}}}{{trim|{{{6}}}}}/60+{{trim|{{{4|+}}}}}{{trim|{{{7}}}}}/3600}}&zoom={{#expr:ln{{{8|100000}}}/ln10+1 round 0}}&show_grid=1&show_constellation_lines=1&show_constellation_boundaries=1&show_const_names=1&show_galaxies=1&img_source=IMG_all {{trim|{{{1}}}}}<sup>h</sup> {{trim|{{{2}}}}}<sup>m</sup> {{trim|{{{3}}}}}<sup>s</sup>, {{#ifeq:{{trim|{{{4}}}}}|-|−|{{trim|{{{4}}}}} }}{{trim|{{{5}}}}}° {{trim|{{{6}}}}}′ {{trim|{{{7}}}}}″]</span>|<indicator name="01-sky-coordinates"><templatestyles src="Template:Sky/styles.css" /><!-- This mostly repeats the previous statement, but i'm to lazy to write a lua module for it, try to keep it in sync --><span class="sky-coordinates-display plainlinks nourlexpansion">[[Celestial coordinate system|Coordinates]]: [[File:Jupiter and moon.png|20px|link=|Sky map]] [http://www.wikisky.org/?ra={{#expr:{{trim|{{{1}}}}}+{{trim|{{{2}}}}}/60+{{trim|{{{3}}}}}/3600}}&de={{#expr:{{trim|{{{4|+}}}}}{{trim|{{{5}}}}}+{{trim|{{{4|+}}}}}{{trim|{{{6}}}}}/60+{{trim|{{{4|+}}}}}{{trim|{{{7}}}}}/3600}}&zoom={{#expr:ln{{{8|100000}}}/ln10+1 round 0}}&show_grid=1&show_constellation_lines=1&show_constellation_boundaries=1&show_const_names=1&show_galaxies=1&img_source=IMG_all {{trim|{{{1}}}}}<sup>h</sup> {{trim|{{{2}}}}}<sup>m</sup> {{trim|{{{3}}}}}<sup>s</sup>, {{#ifeq:{{trim|{{{4}}}}}|-|−|{{trim|{{{4}}}}} }}{{trim|{{{5}}}}}° {{trim|{{{6}}}}}′ {{trim|{{{7}}}}}″]</span></indicator> }}</includeonly><noinclude>{{documentation}}</noinclude> 0820a25c62d725441979785de033585a0ffa870e Energy 0 25 53 52 2022-07-17T09:16:17Z SpaceMan 2 1 revision imported: Energy wikitext text/x-wiki Energy of a body is defined as the capacity or ability of the body to do [[Work]]. ==Forms of energy== ===Mechanical energy=== It includes kinetic and potential energy. '''Kinetic energy''' The energy possessed by a body by the virtue of its motion is called kinetic energy. An object in motion has the ability to do work and hence possesses kinetic energy. Examples of Kinetic Energy (1) Wind possesses kinetic energy and can run wind mill. (1) The kinetic energy of flowing water is used to generate electricity. (ii) A bullet fired from a gun possesses kinetic energy and can penetrate a target. Formula Kinetic energy = 1/2 *mv² Where m = mass and v² = velocity squared '''Potential energy''' The energy possessed by a body by the virtue of its position([[displacement]]) or its configuration (shape or size) is called potential energy. An object may have the capacity of doing work as a result of its position in a gravitational([[gravity]]) field, an electric field or a magnetic field. Potential energy may be positive or negative. Potential energy is often referred as stored energy. Examples of Potential Energy (1) The heavy ball of a demolition machine has potential energy when it is held at an elevated position. (i) A stone lying on the ground has no energy so it cannot do any work. If this stone is lifted to the roof of a house, the work has been done in lifting this stone against the force of gravity. This work gets stored up in the stone in the form of potential energy. (ii) The water stored at height in a dam has potential energy. If it is allowed to fall, the falling water has the ability to rotate turbine to generate electricity. (M) A stone resting on the edge of a cliff has potential energy due to its position in the earth's gravitational field. If it falls, the force of gravity which is equal to the stone's weight will act on it until it strikes the ground. The stone's potential energy is equal to the product of its weight and distance it can fall through. (1) Elastic Potential Energy The energy possessed by a body due to the change in its shape is called as elastic potential energy. The change in shape of the body can be brought by compressing, stretching or bending. For this change, some work has to be done. This work gets stored in the form of elastic potential energy. When this deformed body is released it regains its original position and potential energy is given out in some other form of energy. (B) "The gravitational potential energy of an object at a point above the ground is defined as the as the work done is raising it from the ground to that point against gravity without any [[acceleration]]" Formula Work (w) = Mass (M) * Gravity (g) * Displacement (S) or w = mg * s Potential energy = mg * h ===Heat energy=== Heat can be defined as the form of energy that is transferred between two points due to the presence of a [[temperature]] difference between the two points. When water boils, it changes to steam. The steam possesses heat energy because it has the ability to do work such as to run stear engines, turbine etc. The heat produced by the burning of petrol in a car engine provides the energy needed to run the car. ===Nuclear energy=== The energy stored in the nucleus of an atom is called nuclear energy. The energy stored in the nuclei of atoms can be obtained by carrying out two types of nuclear reactions called nuclear fusion and nuclear fission. c9ad0cf3f0a960b707ef98e06b087a2ec4630142 Kepler 0 26 55 54 2022-07-17T09:20:50Z SpaceMan 2 1 revision imported: Johannes Kepler wikitext text/x-wiki Johannes Kepler was a German [[astronomer]], [[mathematician]], [[astrologer]], natural philosopher and writer on music.[5] He is a key figure in the 17th-century Scientific Revolution, best known for his laws of planetary motion, and his books Astronomia nova, Harmonice Mundi, and Epitome Astronomiae Copernicanae. These works also provided one of the foundations for [[Isaac Newton]] theory of universal gravitation([[Gravity]]). {| class="wikitable" |+Facts |- |Born |27 December 1571 Free Imperial City of Weil der Stadt, Holy Roman Empire |- |Died |15 November 1630 (aged 58) |- |Nationality |German |- |Known for |[[Kepler's laws of planetary motion]] Kepler conjecture Rudolphine Tables |- |Fields |[[Astronomy]], [[astrology]], [[mathematics]], natural philosophy |} 3645e8bbf01a9572c47839bad9c98471c4335cf1 MediaWiki:Citizen-footer-desc 8 27 58 2022-07-17T09:26:28Z SpaceMan 2 Created blank page wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Template:Odlist 10 164 343 2022-07-22T15:52:32Z Canopus >Shāntián Tàiláng 0 wikitext text/x-wiki {{comma separated entries <!-- Traditional/proper names, or exoplanet star designations --> | {{{name<includeonly>|</includeonly>}}} | {{{name2<includeonly>|</includeonly>}}} | {{{name3<includeonly>|</includeonly>}}} | {{{name4<includeonly>|</includeonly>}}} | {{{name5<includeonly>|</includeonly>}}} <!-- Bayer, Flamsteed, Gould, and variable star designations --> | {{#if:{{{B|}}} |[[Bayer designation|{{{B}}}]]}} | {{#if:{{{F|}}} |[[Flamsteed designation|{{{F}}}]]}} | {{#if:{{{Gould|}}}|[[Gould designation|{{{Gould}}}]]}} | {{#if:{{{V|}}} |[[Variable star designation|{{{V}}}]]}} | {{#if:{{{NSV|}}} |[[New Catalogue of Suspected Variable Stars|NSV]]&nbsp;{{{NSV}}}}} <!-- Commonly used designations like HD, HIP, HR --> | {{#if:{{{AG|}}} |{{nowrap|[[Astronomische Gesellschaft Katalog|AG]]{{Str rep|{{{AG}}}|-|−}}}}}} | {{#if:{{{BD<includeonly>|</includeonly>}}} |{{nowrap|[[Bonner Durchmusterung|BD]]{{Str rep|{{{BD}}}|-|−}}}}}} | {{#if:{{{CD|}}} |{{nowrap|[[Cordoba Durchmusterung|CD]]{{Str rep|{{{CD}}}|-|−}}}}}} | {{#if:{{{CP|}}} |{{nowrap|[[Cape Photographic Durchmusterung|CPD]]{{Str rep|{{{CP}}}|-|−}}}}}} | {{#if:{{{CPD|}}} |{{nowrap|[[Cape Photographic Durchmusterung|CPD]]{{Str rep|{{{CPD}}}|-|−}}}}}} | {{#if:{{{FK5|}}} |[[Fifth Fundamental Catalogue|FK5]]&nbsp;{{{FK5}}}}} | {{#if:{{{Gaia DR1|}}} |{{nowrap|[[Star_catalogue#Gaia_Catalogue|Gaia DR1]]&nbsp;{{{Gaia DR1}}}}}}} | {{#if:{{{Gaia DR2|}}} |{{nowrap|[[Star_catalogue#Gaia_Catalogue|Gaia DR2]]&nbsp;{{{Gaia DR2}}}}}}} | {{#if:{{{GC|}}} |[[Boss General Catalogue|GC]]&nbsp;{{{GC}}}}} | {{#if:{{{GJ<includeonly>|</includeonly>}}} |[[Gliese Catalogue of Nearby Stars|GJ]]&nbsp;{{{GJ}}}}} | {{#if:{{{GJ2<includeonly>|</includeonly>}}} |GJ&nbsp;{{{GJ2}}}}} | {{#if:{{{HD<includeonly>|</includeonly>}}} |[[Henry Draper Catalogue|HD]]&nbsp;{{{HD}}}}} | {{#if:{{{HIP<includeonly>|</includeonly>}}} |[[Hipparcos Catalogue|HIP]]&nbsp;{{{HIP}}}}} | {{#if:{{{HR<includeonly>|</includeonly>}}} |[[Harvard Revised catalogue|HR]]&nbsp;{{{HR}}}}} | {{#if:{{{SAO<includeonly>|</includeonly>}}} |[[Smithsonian Astrophysical Observatory Star Catalog|SAO]]&nbsp;{{{SAO}}}}} | {{#if:{{{PPM|}}} |[[Position and proper motion catalogue|PPM]]&nbsp;{{{PPM}}}}} <!-- Double star catalogs --> | {{#if:{{{ADS|}}} |[[Aitken Double Star Catalogue|ADS]]&nbsp;{{{ADS}}}}} | {{#if:{{{CCDM|}}} |{{nowrap|[[Catalog of Components of Double and Multiple Stars|CCDM]] {{{CCDM}}}}}}} | {{#if:{{{WDS<includeonly>|</includeonly>}}} |{{nowrap|[[Washington Double Star Catalog|WDS]] {{{WDS}}}}}}} | {{#if:{{{DC|}}} |[[Discovery code|{{{DC}}}]]}} <!-- Nearby/high-proper-motion star catalogues and the like--> | {{#if:{{{AC|}}} |[[Carte du Ciel|AC]]&nbsp;{{{AC}}}}} | {{#if:{{{BPM|}}} |[[Bruce Proper Motion survey|BPM]]&nbsp;{{{BPM}}}}} | {{#if:{{{Ci 18|}}}|[[Cincinnati Observatory|Ci]]&nbsp;18&nbsp;{{{Ci 18}}}}} | {{#if:{{{Ci 20|}}}|[[Cincinnati Observatory|Ci]]&nbsp;20&nbsp;{{{Ci 20}}}}} | {{#if:{{{EGGR|}}} |[[Olin J. Eggen|EG]][[Jesse L. Greenstein|GR]]&nbsp;{{{EGGR}}}}} | {{#if:{{{G|}}} |{{nowrap|[[Henry L. Giclas catalogue|G]] {{{G}}}}}}} | {{#if:{{{G2|}}} |{{nowrap|[[Henry L. Giclas catalogue|G]] {{{G2}}}}}}} | {{#if:{{{G3|}}} |{{nowrap|[[Henry L. Giclas catalogue|G]] {{{G3}}}}}}} | {{#if:{{{L|}}} |[[Luyten|L]]&nbsp;{{{L}}}}} | {{#if:{{{LAL|}}} |[[Histoire céleste française|LAL]]&nbsp;{{{LAL}}}}} | {{#if:{{{LAWD|}}} |[[Luyten Atlas of White Dwarfs|LAWD]]&nbsp;{{{LAWD}}}}} | {{#if:{{{LFT|}}} |[[Luyten Five-Tenths catalogue|LFT]]&nbsp;{{{LFT}}}}} | {{#if:{{{LHS|}}} |[[Luyten Half-Second Catalogue|LHS]]&nbsp;{{{LHS}}}}} | {{#if:{{{LP|}}} |[[Luyten-Palomar proper motion catalogue|LP]]&nbsp;{{{LP}}}}} | {{#if:{{{LPM|}}} |[[Luyten Proper-Motion Catalogue|LPM]]&nbsp;{{{LPM}}}}} | {{#if:{{{LSPM|}}} |{{nowrap|[[LSPM-North Catalog|LSPM]] {{{LSPM}}}}}}} | {{#if:{{{LTT|}}} |[[Luyten Two-Tenths catalogue|LTT]]&nbsp;{{{LTT}}}}} | {{#if:{{{NLTT|}}} |[[NLTT]]&nbsp;{{{NLTT}}}}} | {{#if:{{{PLX|}}} |[[General Catalogue of Trigonometric Parallaxes|PLX]]&nbsp;{{{PLX}}}}} | {{#if:{{{PM|}}} |[[Proper motion|PM]]&nbsp;{{{PM}}}}} | {{#if:{{{PM2|}}} |[[Proper motion|PM]]&nbsp;{{{PM2}}}}} | {{#if:{{{Ross|}}} |[[Ross catalogue|Ross]]&nbsp;{{{Ross}}}}} | {{#if:{{{SCR|}}} |{{nowrap|[[Super-COSMOS RECONS|SCR]]&nbsp;{{{SCR}}}}}}} | {{#if:{{{WD|}}} |{{nowrap|[[White dwarf|WD]]&nbsp;{{{WD}}}}}}} | {{#if:{{{WD2|}}} |{{nowrap|[[White dwarf|WD]]&nbsp;{{{WD2}}}}}}} | {{#if:{{{WD3|}}} |{{nowrap|[[White dwarf|WD]]&nbsp;{{{WD3}}}}}}} | {{#if:{{{Wolf|}}} |[[Max Wolf|Wolf]]&nbsp;{{{Wolf}}}}} <!-- Exoplanet surveys --> | {{#if:{{{Kepler|}}} |{{nowrap|[[Kepler space telescope|Kepler]]-{{{Kepler}}}}}}} | {{#if:{{{KOI|}}} |{{nowrap|[[Kepler object of interest|KOI]]-{{{KOI}}}}}}} | {{#if:{{{KIC|}}} |{{nowrap|[[Kepler Input Catalog|KIC]]&nbsp;{{{KIC}}}}}}} | {{#if:{{{EPIC|}}} |{{nowrap|[[Ecliptic Plane Input Catalog|EPIC]]&nbsp;{{{EPIC}}}}}}} | {{#if:{{{TOI|}}} |{{nowrap|[[Tess object of interest|TOI]]-{{{TOI}}}}}}} | {{#if:{{{TIC|}}} |{{nowrap|[[TESS Input Catalog|TIC]]&nbsp;{{{TIC}}}}}}} <!-- Extensive star surveys --> | {{#if:{{{TYC|}}} |{{nowrap|[[Tycho Catalogue|TYC]]&nbsp;{{{TYC}}}}}}} | {{#if:{{{GCRV|}}} |{{nowrap|[[GCRV]]&nbsp;{{{GCRV}}}}}}} | {{#if:{{{GSC|}}} |{{nowrap|[[Guide Star Catalog|GSC]]&nbsp;{{{GSC}}}}}}} | {{#if:{{{IRAS|}}} |{{nowrap|[[IRAS]] {{{IRAS}}}}}}} | {{#if:{{{2MASS|}}}|{{nowrap|[[2MASS]] {{{2MASS}}}}}}} | {{#if:{{{2MASX|}}}|{{nowrap|[[2MASX]] {{{2MASX}}}}}}} | {{#if:{{{DENIS|}}}|{{nowrap|[[DENIS]] {{{DENIS}}}}}}} | {{#if:{{{WISE|}}} |{{nowrap|[[Wide-field Infrared Survey Explorer|WISE]] {{{WISE}}}}}}} | {{#if:{{{WISEA|}}}|{{nowrap|[[Wide-field Infrared Survey Explorer|WISEA]] {{{WISEA}}}}}}} <!-- Galaxy catalogs --> | {{#if:{{{NGC|}}} |{{nowrap|[[New General Catalogue|NGC]] {{{NGC}}}}}}} | {{#if:{{{IC|}}} |{{nowrap|[[Index Catalogue|IC]] {{{IC}}}}}}} | {{#if:{{{Arp|}}} |{{nowrap|[[Atlas of Peculiar Galaxies|Arp]] {{{Arp}}}}}}} | {{#if:{{{UGC|}}} |{{nowrap|[[Uppsala General Catalogue|UGC]] {{{UGC}}}}}}} | {{#if:{{{UGCA|}}} |{{nowrap|[[UGCA]] {{{UGCA}}}}}}} | {{#if:{{{LEDA|}}} |{{nowrap|[[Lyon-Meudon Extragalactic Database|LEDA]] {{{LEDA}}}}}}} | {{#if:{{{MCG|}}} |{{nowrap|[[Morphological Catalogue of Galaxies|MCG]] {{{MCG}}}}}}} | {{#if:{{{MRK|}}} |{{nowrap|[[Markarian galaxies|Mrk]] {{{MRK}}}}}}} | {{#if:{{{PGC|}}} |{{nowrap|[[Principal Galaxies Catalogue|PGC]] {{{PGC}}}}}}} | {{#if:{{{CGCG|}}} |{{nowrap|[[Catalogue of Galaxies and of Clusters of Galaxies|CGCG]] {{{CGCG}}}}}}} | {{#if:{{{VV|}}} |{{nowrap|[[Vorontsov-Vel'yaminov Interacting Galaxies|VV]] {{{VV}}}}}}} | {{#if:{{{KPG|}}} |KPG&nbsp;{{{KPG}}}}} | {{#if:{{{SDSS|}}} |{{nowrap|[[Sloan Digital Sky Survey|SDSS]] {{{SDSS}}}}}}} }}<noinclude> {{documentation|content= This template may be used to create a list of other designations within [[Template:Starbox catalog]] or [[Template:Infobox galaxy]]. == Usage == A blank template with all the possible parameters is given below. You may delete any unused parameters. <pre> {{odlist | name = | name2 = | name3 = | name4 = | name5 = | 2MASS = <!-- Two Micron All-Sky Survey --> | AC = <!-- Carte du Ciel --> | AG = <!-- Astronomische Gesellschaft Katalog --> | ADS = <!-- Aitken Double Star Catalogue --> | B = <!-- Bayer designation --> | BD = <!-- Bonner Durchmusterung --> | BPM = <!-- Bruce Proper Motion survey --> | CCDM = <!-- Catalogue of Components of Double and Multiple Stars --> | CD = <!-- Cordoba Durchmusterung --> | Ci 18 = <!-- Cincinnati Observatory --> | Ci 20 = <!-- Cincinnati Observatory --> | CP = <!-- Cape Photographic Durchmusterung --> | CPD = <!-- Cape Photographic Durchmusterung --> | DC = <!-- Washington Double Star Catalog discovery code (see WDS) --> | DENIS = <!-- Deep Near Infrared Survey of the Southern Sky --> | EGGR = <!-- Olin J. Eggen --> | EPIC = <!-- Ecliptic Plane Input Catalog --> | F = <!-- Flamsteed designation --> | FK5 = <!-- Fifth Fundamental Catalogue --> | G = <!-- Henry L. Giclas catalogue --> | G2 = <!-- Henry L. Giclas catalogue --> | G3 = <!-- Henry L. Giclas catalogue --> | Gaia DR1 = <!-- Gaia data release 1 --> | Gaia DR2 = <!-- Gaia data release 2 --> | GCRV = <!-- General Catalogue of Stellar Radial Velocities --> | GJ = <!-- Gliese-Jahreiss catalogue --> | GJ2 = <!-- Gliese-Jahreiss catalogue --> | Gould = <!-- Uranometria Argentina catalogue --> | GSC = <!-- Guide Star Catalog --> | HD = <!-- Henry Draper Catalogue --> | HIP = <!-- Hipparcos Catalogue --> | HR = <!-- Harvard Revised catalogue --> | IRAS = <!-- Infrared Astronomical Satellite --> | Kepler = <!-- Kepler --> | KIC = <!-- Kepler Input Catalogue --> | KOI = <!-- Kepler Object of Interest --> | L = <!-- Luyten --> | LAL = <!-- Histoire céleste française --> | LAWD = <!-- Luyten Atlas of White Dwarfs --> | LDS = <!-- Luyten Double Stars catalogue --> | LP = <!-- Luyten-Palomar proper motion catalogue --> | LPM = <!-- Luyten Proper-Motion Catalogue --> | LFT = <!-- Luyten Five-Tenths catalogue --> | LHS = <!-- Luyten Half-Second Catalogue --> | LSPM = <!-- LSPM-North Catalog --> | LTT = <!-- Luyten Two-Tenths catalogue --> | NLTT = <!-- New Luyten Two-Tenths Catalogue --> | NSV = <!-- New Catalogue of Suspected Variable Stars --> | PLX = <!-- General Catalogue of Trigonometric Parallaxes --> | PM = <!-- Proper motion --> | PM2 = <!-- Proper motion --> | PPM = <!-- Position and proper motion catalogue --> | Ross = <!-- Ross catalogue --> | SAO = <!-- Smithsonian Astrophysical Observatory Star Catalogue --> | SCR = <!-- Super-COSMOS RECONS --> | TOI = <!-- Tess Object of Interest --> | TYC = <!-- Tycho Catalogue --> | V = <!-- Variable star designation --> | WD = <!-- White dwarf --> | WD2 = <!-- White dwarf --> | WD3 = <!-- White dwarf --> | WDS = <!-- Washington Double Star Catalog --> | WISE = <!-- Wide-field Infrared Survey Explorer --> | WISEA = <!-- Wide-field Infrared Survey Explorer - All-Sky --> | Wolf = <!-- Max Wolf --> }}</pre> For galaxies, use this one: <pre> {{odlist | name = | name2 = | name3 = | name4 = | name5 = | Arp = <!-- Atlas of Peculiar Galaxies --> | IC = <!-- Index Catalogue --> | LEDA = <!-- Lyon-Meudon Extragalactic Database --> | MCG = <!-- Morphological Catalogue of Galaxies --> | MRK = <!-- Markarian galaxies --> | NGC = <!-- New General Catalogue --> | PGC = <!-- Principal Galaxies Catalogue --> | UGC = <!-- Uppsala General Catalogue --> | UGCA = <!-- Uppsala General Catalogue Addendum --> | 2MASS = <!-- Two Micron All-Sky Survey --> | 2MASX = <!-- Two Micron All-Sky Survey Extended Source Catalog --> | CGCG = <!-- Catalogue of Galaxies and of Clusters of Galaxies --> | VV = <!-- Vorontsov-Vel'yaminov Interacting Galaxies --> | KPG = <!-- Karachentsev Catalogue of Isolated Pairs of Galaxies --> | SDSS = <!-- Sloan Digital Sky Survey --> }}</pre> [[Category:Astronomy templates]] }}</noinclude> a5bf09051821f2310a8126a5829dc0cbd7e51dd9 Module:Portal/images/a 828 117 249 2022-07-27T15:07:14Z Canopus >Buaidh 0 ["algeria"] = "Flag of Algeria.svg|border|link=|alt=flag", Scribunto text/plain --[==[ This is the "A" list of portal image names. It contains a list of portal images for use with [[Module:Portal]] -- for portal names that start with the letter "A". For aliases to existing portal names, and for portal names that -- start with other letters, please use the appropriate page from the following list: -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/o]] - for portal names beginning with "O". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/s]] - for portal names beginning with "S". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- [[Module:Portal/images/aliases]] - for adding aliases for existing portal names. Use this page for variations -- in spelling and diacritics, etc., no matter what letter the portal begins with. -- When adding entries, please use alphabetical order. The format of the images table entries is as follows: -- ["portal name"] = "image.svg", -- The portal name should be the name of your portal, in lower case. For example, the portal name for -- "Portal:United Kingdom" would be "united kingdom". The image name should be capitalised normally, and the "File:" -- namespace prefix should be -- omitted. ]==] return { ["airports"] = "Round Landmark Icon Airport.svg|link=|alt=", ["aarhus"] = "Coat of arms of Aarhus.svg|alt=icon", ["abkhazia"] = "Flag of Abkhazia.svg|border|link=|alt=flag", ["aboriginal peoples in canada"] = "Aboriginal War Veterans monument (close).JPG|alt=icon", ["abu dhabi"] = "Flag of Abu Dhabi.svg|border|link=|alt=flag", ["acipenseriformes"] = "Acipenser oxyrhynchus (edit).png|link=|alt=icon", ["actors and filmmakers"] = "Charlie Chaplin 1912.jpg|link=|alt=photo", ["ac/dc"] = "Acdc logo band.svg|link=|alt=", ["academy award"] = "Video-x-generic.svg|link=|alt=", ["acadia"] = "Flag of Acadia.svg|border|link=|alt=flag", ["acc"] = "ACC Map crop 2014.png|alt=icon", ["adelaide"] = "Escudo de Adelaida.png|alt=icon", ["adobe flash"] = "Adobe Flash Player v11 icon.png|link=|alt=logo", ["advent"] = "Candle4.png|alt=Advent candle", ["aerosmith"] = "Joe Perry 1.jpg|alt=icon", ["aerospace biography"] = "Armstrong-Spencom01.jpg|link=|alt=photo", ["aesthetics"] = "Morning Glory Flower square.jpg|alt=icon", ["afghanistan"] = "Flag of the Taliban.svg|border|link=|alt=flag", ["africa"] = "Africa (orthographic projection).svg|link=|alt=map", ["african american"] = "Kleed- Stichting Nationaal Museum van Wereldculturen - RV-5899-18 (cropped).jpg|alt=icon", ["african cuisine"] = "Africa icon.png|link=|alt=", ["african diaspora"] = "Moromi.png|link=|alt=map", ["african union"] = "Flag of the African Union.svg|border|link=|alt=flag", ["afro-eurasia"] = "Afro-Eurasia (orthographic projection).svg|link=|alt=map", ["agriculture"] = "Veranotrigo.jpg|alt=icon", ["agriculture and agronomy"] = "Veranotrigo.jpg|alt=icon", ["agropedia"] = "Farmer plowing in Fahrenwalde, Mecklenburg-Vorpommern, Germany.jpg|alt=icon", ["aguascalientes"] = "Flag of Aguascalientes.svg|border|link=|alt=flag", ["ahmadiyya"] = "White Minaret Symbol.png|alt=icon", ["ahmedabad"] = "Mosque of Sidi Sayed Jaali.JPG|alt=icon", ["ai"] = "ArtificialFictionBrain.png|alt=icon", ["ajman"] = "Flag of Ajman.svg|link=|alt=flag", ["akb48"] = "AKB48 logo2.svg|link=|alt=", ["alabama"] = "Flag of Alabama.svg|border|link=|alt=flag", ["alaska"] = "Flag of Alaska.svg|border|link=|alt=flag", ["albania"] = "Flag of Albania.svg|border|link=|alt=flag", ["albemarle county"] = "Monticello 2010-10-29.jpg|link=|alt=photo", ["alberta"] = "Flag of Alberta.svg|border|link=|alt=flag", ["alcoholic drinks"] = "Mitch (cocktail).jpg|link=|alt=", ["a-league"] = "Soccer ball.svg|alt=icon", ["algae"] = "Algae Graphic.svg|link=|alt=icon", ["algebra"] = "Arithmetic symbols.svg|link=|alt=", ["algeria"] = "Flag of Algeria.svg|border|link=|alt=flag", ["almaty"] = "Flag of Almaty.svg|alt=flag", ["alps"] = "Palü en Diavolezza.jpg|alt=icon", ["alternative medicine"] = "Rod of Asclepius2.svg|alt=icon", ["alternative rock"] = "Guitar 1.svg|link=|alt=icon", ["american animation"] = "Animation disc US.svg|link=|alt=icon", ["american cinema"] = "Cinema of the United States.svg|link=|alt=icon", ["american civil war"] = "Acw bs 7a.png|border|link=|alt=", ["american cuisine"] = "Americanbandstand-1.jpg|link=|alt=", ["american football"] = "American football.svg|link=|alt=icon", ["american football league"] = "AFL Trophy alt.png|link=|alt=trophy", ["american music"] = "Musical Notes USA.svg|link=|alt=icon", ["american old west"] = "Frederic Remington Dismounted Moving Led Horses.jpg|link=|alt=painting", ["american open wheel racing"] = "JuanMontoya2015Indy500.JPG|link=|alt=photo", ["american revolutionary war"] = "Washington Crossing the Delaware by Emanuel Leutze, MMA-NYC, 1851.jpg|border|link=|alt=", ["american samoa"] = "Flag of American Samoa.svg|border|link=|alt=flag", ["american television"] = "USA flag on television.svg|link=|alt=icon", ["americas"] = "Americas (orthographic projection).svg|link=|alt=map", ["amiga"] = "Boingball.png|link=|alt=", ["amphibians"] = "Frog (2546) - The Noun Project.svg|link=|alt=", ["amphibians and reptiles"] = "Lizardicon.svg|link=|alt=", ["amusement parks"] = "Roller Coaster Icon.svg|link=|alt=", ["anabaptism"] = "Dirk.willems.rescue.ncs.jpg|link=|alt=", ["analysis"] = "Nuvola apps kmplot.svg|alt=icon", ["analytical chemistry"] = "Nuvola apps edu science.svg|alt=icon", ["anarchism"] = "BlackFlagSymbol.svg|border|link=|alt=flag", ["andes"] = "Ausangate-hillside-MT.jpg|alt=", ["andorra la vella"] = "Flag of Andorra la Vella.svg|alt=flag", ["apples"] = "Apple icon 1.png|link=|alt=", ["argentine cuisine"] = "Argentine cuisine title.jpg|link=|alt=", ["anatomy"] = "Anatomy posture and body mechanics 08.web.jpg|alt=icon", ["ancient egypt"] = "Pyramidi aavikolla.png|link=|alt=", ["ancient germanic culture"] = "Mjollnir icon.png|link=|alt=", ["ancient greece"] = "Parthenon from west.jpg|link=|alt=", ["ancient japan"] = "Shiki no Fuji, Ōmuro fukin by Takahashi Shōtei.jpg|link=|alt=", ["ancient near east"] = "Babylonlion.JPG|link=|alt=", ["ancient rome"] = "SPQRomani.svg|link=|alt=", ["andaman and nicobar islands"] = "India Andaman and Nicobar Islands locator map.svg|border|link=|alt=map", ["andhra pradesh"] = "Archbridgegodavari.JPG|alt=icon", ["andorra"] = "Flag of Andorra.svg|border|link=|alt=flag", ["android (operating system)"] = "Android robot.svg|link=|alt=icon", ["anglicanism"] = "Canterbury cathedral.jpg|link=|alt=", ["anglo-saxon england"] = "Peterborough Chronicle cropped.jpg|link=|alt=", ["angola"] = "Flag of Angola.svg|border|link=|alt=flag", ["anguilla"] = "Flag of Anguilla.svg|border|link=|alt=flag", ["animal rights"] = "Paw (Animal Rights symbol).svg|alt=icon", ["animals"] = "Caribou from Wagon Trails.jpg|alt=icon", ["animation"] = "Animation disc.svg|alt=icon", ["animation/canadian animation work group"] = "Animation disc Maple Leaf.svg|alt=icon", ["anime and manga"] = "Wikipe-tan face.svg|alt=icon", ["antarctica"] = "Antarctica (orthographic projection).svg|link=|alt=map", ["anthropology"] = "Moai Easter Island InvMH-35-61-1.jpg|link=|alt=", ["antigua and barbuda"] = "Flag of Antigua and Barbuda.svg|border|link=|alt=flag", ["antwerp"] = "Coat of arms of Antwerp (City).svg|alt=icon", ["appalachia"] = "Appalachian region of United States.png|border|link=|alt=map", ["apple inc."] = "Apple logo black.svg|link=|alt=", ["applied science"] = "Metallurgy stub icon.svg|link=|alt=icon", ["aquarium fish"] = "Pterois antennata-3.jpg|link=|alt=", ["arab world"] = "Flag of the Arab League.svg|border|link=|alt=flag", ["arabic language"] = "Arabic-dad-letter.svg|link=Arabic language|alt=icon", ["archaeology"] = "Stonehenge Closeup.jpg|link=|alt=", ["architecture"] = "P parthenon.svg|alt=icon", ["arctic"] = "Arctic (orthographic projection).svg|link=|alt=map", ["argentina"] = "Flag of Argentina.svg|border|link=|alt=flag", ["arithmetic"] = "Arithmetic symbols.svg|link=|alt=", ["arizona"] = "Flag of Arizona.svg|border|link=|alt=flag", ["arkansas"] = "Flag of Arkansas.svg|border|link=|alt=flag", ["armenia"] = "Flag of Armenia.svg|border|link=|alt=flag", ["arminianism"] = "Arminius 5 flopped and cropped.png|link=|alt=", ["arunachal pradesh"] = "India Arunachal Pradesh locator map.svg|link=|alt=map", ["art"] = "Ballerina-icon.jpg|alt=icon", ["arthropods"] = "Cercophonius squama.jpg|alt=icon", ["artificial intelligence"] = "Animation2.gif|alt=icon", ["arts"] = "Nuvola apps package graphics.png|alt=icon", ["artsakh"] = "Flag of Artsakh.svg|border|link=|alt=flag", ["arts and entertainment"] = "Meryl in 1990.jpg|link=|alt=photo", ["aruba"] = "Flag of Aruba.svg|border|link=|alt=flag", ["asia"] = "Asia (orthographic projection).svg|alt=icon", ["asian games"] = "Asian Games logo01.png|link=|alt=", ["aspect ratio 1.000"] = "Flag of Switzerland.svg|link=|alt=image", ["aspect ratio 1.333"] = "Flag of Gabon.svg|link=|alt=image", ["aspect ratio 1.400"] = "Flag of Kosovo.svg|link=|alt=image", ["aspect ratio 1.500"] = "Flag of the European Union.svg|link=|alt=image", ["aspect ratio 1.667"] = "Flag of Bangladesh.svg|link=|alt=image", ["aspect ratio 2.000"] = "Flag of the United Kingdom.svg|link=|alt=image", ["assam"] = "Seal of Assam.png|link=|alt=", ["association football"] = "Soccer ball.svg|alt=icon", ["assyrians"] = "Flag of Assyria.svg|border|link=|alt=flag", ["astrobiology"] = "PIA01130 Interior of Europa.jpg|link=|alt=", ["astrology"] = "Astrologia-tynkä.jpg|link=|alt=", ["astronomy"] = "Crab Nebula.jpg|link=|alt=", ["atheism"] = "Atheism template.svg|alt=icon", ["athletics"] = "Athletics pictogram.svg|link=|alt=", ["atlanta"] = "Atlflag.svg|link=|alt=flag", ["atlantic ocean"] = "Atlantic Ocean - en IHO.png|link=|alt=map", ["atlas"] = "World map green.png|alt=icon", ["atmospheric science"] = "Cumulus clouds in fair weather.jpeg|link=|alt=icon", ["atoms"] = "Stylised atom with three Bohr model orbits and stylised nucleus.svg|link=|alt=", ["austin"] = "Sixth Street Austin.jpg|alt=icon", ["australasia"] = "Oceania (orthographic projection).svg|link=|alt=map", ["australia"] = "Flag of Australia.svg|border|link=|alt=flag", ["australian army"] = "Australian Army Emblem Transparent.png|border|link=|alt=icon", ["australian capital territory"] = "Flag of the Australian Capital Territory.svg|border|link=|alt=flag", ["australian continent"] = "Australia (orthographic projection).svg|link=|alt=map", ["australian roads"] = "Australia road sign W5-29.svg|alt=icon", ["australian rules football"] = "Sherrin-transparent.png|link=|alt=", ["austria"] = "Flag of Austria.svg|border|link=|alt=flag", ["austria-hungary"] = "Wappen Österreich-Ungarn 1916 (Klein).png|link=|alt=", ["automobiles"] = "Sportcar sergio luiz ara 01.svg|link=|alt=", ["automotive industry in japan"] = "Car with Driver-Silhouette.svg|link=|alt=", ["aviation"] = "Aviacionavion.png|link=|alt=", ["avril lavigne"] = "LetGo.jpg|alt=icon", ["ayyavazhi"] = "Ayyavazh logo transperent.png|alt=icon", ["azad kashmir"] = "Flag of Azad Kashmir.svg|border|link=|alt=flag", ["azerbaijan"] = "Flag of Azerbaijan.svg|border|link=|alt=flag", ["azores"] = "Flag of the Azores.svg|border|link=|alt=flag" } 2ed9709a584c9486757ce4112bbf87096eb6b3be Module:Portal/images/aliases 828 122 259 2022-07-28T02:55:56Z Canopus >Buaidh 0 ["south georgia and the south sandwich islands"] = {"south georgia", "south sandwich islands", "gs", "sgs"}, Scribunto text/plain --[==[ This is the "aliases" list of portal image names. It contains a list of portal image aliases for use with [[Module:Portal]]. -- The aliases can be used to point to an existing portal image entry. For portals who do not yet have a portal image entry, please -- use the appropriate page from the following list instead: -- [[Module:Portal/images/a]] - for portal names beginning with "A". -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/o]] - for portal names beginning with "O". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/s]] - for portal names beginning with "S". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- When adding entries, please use alphabetical order. The format of the alias table entries is as follows: -- ["portal name"] = {"alias 1", "alias 2", "alias 3"}, -- Both the portal name and the alias names should be in lower case, and the "Portal:" namespace prefix -- should be omitted. For example, if you wanted "UK" to be an alias for "Portal:United Kingdom", then the -- alias name would be "uk" and the portal name would be "united kingdom". ]==] return { ["1990s"] = {"1990's"}, ["2000s"] = {"2000's"}, ["ac/dc"] = {"ac dc"}, ["academy award"] = {"academy awards"}, ["african american"] = {"african-american", "african-americans", "african americans"}, ["african union"] = {"au"}, ["agriculture and agronomy"] = {"agriculture"}, ["american civil war"] = {"acw"}, ["american revolutionary war"] = {"american revolution"}, ["amphibians"] = {"amphibian"}, ["aviation"] = {"airplanes"}, ["åland"] = {"åland islands", "aland islands", "aland", "ax", "ala"}, ["albania"] = {"albanian", "al", "alb"}, ["american football"] = {"college football", "arena football league"}, ["android (operating system)"] = {"android", "android os"}, ["apple inc."] = {"apple", "apple inc"}, ["arabic language"] = {"arabic"}, ["archaeology"] = {"archeology"}, ["asian americans"] = {"asian american"}, ["association football"] = {"soccer"}, ["assyrians"] = {"assyria"}, ["atlas"] = {"cartography"}, ["atmospheric science"] = {"atmosphere","atmospheric sciences"}, ["australia"] = {"australian", "aus"}, ["australian capital territory"] = {"canberra"}, ["banks"] = {"bank", "banking"}, ["baseball"] = {"college baseball", "little league"}, ["basketball"] = {"national basketball league of canada", "wnba"}, ["biography"] = {"people", "biographies"}, ["birds"] = {"bird"}, ["björk"] = {"bjork"}, ["books"] = {"book"}, ["brunei"] = {"brunei darussalam", "bn", "brn"}, ["business and economics"] = {"advertising", "business", "economics", "economy", "marketing"}, ["buses"] = {"bus"}, ["california roads"] = {"roads in california"}, ["california state polytechnic university, pomona"] = {"cal poly pomona"}, ["canada"] = {"canadian", "ca", "can"}, ["canadian armed forces"] = {"canadian forces", "military history of canada"}, ["canary islands"] = {"spanish africa"}, ["caribbean"] = {"caribbean sea", "west indies"}, ["cars"] = {"car", "automobile"}, ["cartoon"] = {"cartoons"}, ["catalan-speaking countries"] = {"catalan", "catalonia"}, ["cats"] = {"cat"}, ["celtic studies"] = {"celts"}, ["children's literature"] = {"children's and young adult literature", "children and young adult literature"}, ["china"] = {"chinese", "cn", "chn"}, ["christiantiy"] = {"christ", "christian"}, ["christianity in india"] = {"indian christianity"}, ["classical civilisation"] = {"classical civilization", "classics"}, ["cleveland"] = {"cleveland, ohio"}, ["coconuts"] = {"coconut"}, ["color"] = {"colour"}, ["comedy"] = {"humour", "humor"}, ["commonwealth realms"] = {"commonwealth"}, ["compact disc"] = {"cd", "compact disk"}, ["companies"] = {"company"}, ["computer-generated imagery"] = {"computer generated imagery"}, ["computer programming"] = {"programming"}, ["county kilkenny"] = {"kilkenny"}, ["criminal justice"] = {"crime"}, ["current events"] = {"events"}, ["czech republic"] = {"czechia", "czech"}, ["dallas – fort worth metroplex"] = {"dallas", "dallas-fort worth", "dallas - fort worth metroplex"}, ["democratic republic of the congo"] = {"zaire", "zaïre", "cod", "drc", "the democratic republic of the congo"}, ["denmark"] = {"kingdom of denmark", "danish", "dk", "dnk"}, ["disasters"] = {"disaster"}, ["dravidian languages"] = {"dravidian", "dravidia", "dravidian peoples", "dravidian civilization"}, ["dominican republic"] = {"the dominican republic"}, ["durham, north carolina"] = {"durham nc"}, ["dungeons & dragons"] = {"d&d"}, ["east timor"] = {"timor leste", "tl"}, ["electromagnetism"] = {"em"}, ["english football"] = {"football in england"}, ["english language"] = {"english"}, ["erotica and pornography"] = {"porn", "pornography"}, ["european military history"] = {"military history of europe"}, ["european union"] = {"eu"}, ["evolutionary biology"] = {"evolution"}, ["extinct and endangered species"] = {"extinction", "endangered species"}, ["falkland islands"] = {"falkland", "malvinas", "fk", "flk"}, ["faroe islands"] = {"the faroe islands"}, ["federated states of micronesia"] = {"fm", "fsm"}, ["film"] = {"films"}, ["football"] = {"association football", "soccer", "soccer ball"}, ["formula one"] = {"f1", "formula 1"}, ["free and open-source software"] = {"free and open source software", "free software", "foss", "open source software", "open-source software", "oss"}, ["freedom of speech"] = {"censorship", "free speech"}, ["french and francophone literature"] = {"french literature"}, ["french politics"] = {"politics of france"}, ["gardening"] = {"gardening and horticulture"}, ["gemology and jewelry"] = {"gemmology and jewellery", "gemmology and jewelry", "gemology and jewellery"}, ["georgia (country)"] = {"georgia", "republic of georgia", "ge", "geo"}, ["georgia (u.s. state)"] = {"georgia (state)"}, ["globalization"] = {"globalisation"}, ["gullah"] = {"gullah people"}, ["hawaii"] = {"hawai'i", "hawaiʻi", "us-hi"}, ["hazardous materials"] = {"dangerous goods"}, ["health and fitness"] = {"health"}, ["himalayas"] = {"himalaya region"}, ["hindustani"] = {"hindustani language", "hindustani and allied languages"}, ["hip hop"] = {"hip-hop"}, ["hispanic and latino americans"] = {"hispanic and latino american", "latino and hispanic americans", "latino and hispanic american"}, ["horror fiction"] = {"horror"}, ["horticulture and gardening"] = {"horticulture"}, ["hunger relief"] = {"hunger"}, ["india"] = {"indian", "in", "ind", "republic of india"}, ["indian women"] = {"women of india", "indian women and gender issues"}, ["indiana"] = {"hoosier", "us-in"}, ["indigenous peoples of north america"] = {"indigenous people of north america"}, ["information technology"] = {"computing", "computer science", "it"}, ["insects"] = {"insect"}, ["ireland"] = {"irish"}, ["islam"] = {"muslim history"}, ["islamic state of iraq and the levant"] = {"daesh", "isil", "isis"}, ["islands"] = {"island"}, ["italy"] = {"italian", "ita"}, ["jacksonville, florida"] = {"jacksonville"}, ["kazi nazrul islam"] = {"nazrul"}, ["latter day saint movement"] = {"lds"}, ["lemony snicket"] = {"a series of unfortunate events"}, ["lgbt"] = {"lgbtq", "lgbtqa"}, ["library and information science"] = {"information science"}, ["madonna (entertainer)"] = {"madonna"}, ["mediterranean"] = {"mediterranean sea"}, ["metro detroit"] = {"detroit"}, ["mexico"] = {"méxico", "mx", "mex"}, ["middle tennessee state university"] = {"mtsu"}, ["michigan highways"] = {"highways in michigan"}, ["molecular and cell biology"] = {"molecular and cellular biology"}, ["moldova"] = {"republic of moldova"}, ["mongolia"] = {"mongols"}, ["mountains"] = {"mountain"}, ["music of australia"] = {"australian music"}, ["myanmar"] = {"burma", "burmese", "mm", "mmr"}, ["national register of historic places"] = {"nrhp"}, ["nazism"] = {"nazi germany"}, ["netherlands"] = {"kingdom of the netherlands", "nl", 'nld', 'caribbean netherlands', 'the netherlands', 'dutch empire', 'the dutch empire'}, ["new york"] = {"new york state", "new york (state)", "us-ny"}, ["new york city"] = {"nyc"}, ["new zealand"] = {"nz", "nzl"}, ["north korea"] = {"dprk", "democratic people's republic of korea"}, ["north macedonia"] = {"republic of north macedonia", "mk", "mkd"}, ["north rhine-westphalia"] = {"nrw"}, ["oceans"] = {"ocean", "world ocean"}, ["odisha"] = {"orissa"}, ["opera"] = {"operas"}, ["organized labour"] = {"organised labour", "organized labor"}, ["pakistan"] = {"pakistani", "pk", "pak"}, ["paleontology"] = {"palaeontology"}, ["palestine"] = {"the state of palestine","state of palestine"}, ["paralympic games"] = {"paralympics"}, ["pan-africanism"] = {"pan-african"}, ["people's republic of china"] = {"prc"}, ["pharmacy and pharmacology"] = {"pharmacy"}, ["pitcairn islands"] = {"pitcairn, henderson, ducie and oeno islands"}, ["politics"] = {"government"}, ["prince edward island"] = {"pei", "ca-pe"}, ["protected areas of india"] = {"biodiversity, protected areas & environment of india", "biodiversity of india", "environment of india"}, ["puducherry"] = {"pondicherry", "in-py"}, ["punjab, india"] = {"punjab (india)", "in-pb"}, ["punjab, pakistan"] = {"punjab (pakistan)", "western punjab", "pk-pb"}, ["python programming"] = {"python"}, ["quebec"] = {"québec", "ca-qc"}, ["religion"] = {"religions"}, ["republic of ireland"] = {"éire", "ie", "irl", "irish republicanism"}, ["republic of north macedonia"] = {"north macedonia", "mk", "mkd", "the republic of macedonia", "republic of macedonia"}, ["republic of the congo"] = {"the republic of the congo", "republic of congo", "french congo"}, ["roads of canada"] = {"canada roads"}, ["romani people"] = {"roma", "romani"}, ["saint barthelemy"] = {"saint-barthélemy", "saint barthélemy"}, ["saint helena, ascension and tristan da cunha"] = {"saint helena"}, ["salad dressing"] = {"salad dressings"}, ["sandwich"] = {"sandwiches"}, ["schools"] = {"school"}, ["serer people"] = {"serer"}, ["september 11 attacks"] = {"september 11, 2001"}, ["sexuality"] = {"sex"}, ["soap operas and telenovelas"] = {"soap operas", "telenovelas"}, ["south africa"] = {"za", "zaf"}, ["south georgia and the south sandwich islands"] = {"south georgia", "south sandwich islands", "gs", "sgs"}, ["soviet union"] = {"ussr"}, ["space"] = {"outer space"}, ["spices"] = {"herbs and spices"}, ["sports in canada"] = {"canadian sports", "canadian sport", "sports of canada", "sport in canada"}, ["sports"] = {"sport"}, ["st. john's, newfoundland and labrador"] = {"st. john's"}, ["state of georgia"] = {"georgia (u.s. state)", "georgia usa", "us-ga"}, ["state of mexico"] = {"mexico (state)", "mx-mex"}, ["state university of new york"] = {"suny"}, ["taiwan"] = {"republic of china", "roc", "tw", "twn"}, ["tamil people"] = {"tamil"}, ["tanks"] = {"tank"}, ["telecommunication"] = {"telecommunications", "telecoms", "telecomms", "telecomm", "telecom"}, ["texas a&m university"] = {"texas a&m"}, ["texas tech university"] = {"texas tech"}, ["theatre"] = {"theater"}, ["the bahamas"] = {"bahamas", "bs", "bhs"}, ["the gambia"] = {"gambia", "gm", "gmb"}, ["the legend of zelda"] = {"legend of zelda"}, ["tiruchirappalli"] = {"trichy", "tiruchi"}, ["transportation"] = {"transport"}, ["trauma and orthopaedics"] = {"trauma & orthopaedics"}, ["tropical cyclones"] = {"tropical cyclone"}, ["united arab emirates"] = {"emirates", "ae", "uae", "emirati"}, ["united kingdom"] = {"the united kingdom", "uk", "gb", "gbr", "british", "british overseas territories"}, ["united nations"] = {"un"}, ["united states"] = {"us", "usa", "u.s.", "united states armed forces", "american", "territories of the united states"}, ["united states arms"] = {"united states armed forces", "united states military", "united states military history", "u.s. armed forces", "u.s. military"}, ["united states congress"] = {"u.s. congress"}, ["united states counties"] = {"u.s. counties"}, ["united states presidents"] = {"u.s. presidents"}, ["united states roads"] = {"u.s. roads"}, ["united states state legislatures"] = {"u.s. state legislatures", "us state legislatures"}, ["united states streets"] = {"u.s. streets"}, ["united states supreme court"] = {"u.s. supreme court cases"}, ["united states territories"] = {"territories of the united states"}, ["university of missouri"] = {"mizzou"}, ["university of notre dame"] = {"notre dame"}, ["university of pittsburgh"] = {"pitt"}, ["video games"] = {"vg", "video game"}, ["war"] = {"military"}, ["washington (state)"] = {"washington", "us-wa"}, ["washington, d.c."] = {"district of columbia", "dc", "washington dc", "us-dc"}, ["western asia"] = {"west asia"}, ["western sahara"] = {"sahrawi arab democratic republic", "eh", "esh"}, ["world war i"] = {"first world war"}, ["world war ii"] = {"second world war"}, ["zoos"] = {"zoo"} } 06ad5a8008671463b8305eb44bb61afb68f4f1df Module:Authority control 828 91 197 2022-07-29T20:40:29Z Canopus >MSGJ 0 update syntax for NLK Scribunto text/plain require('Module:No globals') local p = {} local title = mw.title.getCurrentTitle() local namespace = title.namespace local testcases = (string.sub(title.subpageText,1,9) == 'testcases') --[[==========================================================================]] --[[ Category functions ]] --[[==========================================================================]] local function addCat( cat ) if cat and cat ~= '' then return '[[Category:'..cat..']]'..p.redCatLink(cat) end return '' end function p.getCatForId( id ) local cat = '' if namespace == 0 then cat = 'Articles with '..id..' identifiers' end return addCat(cat) end function p.redCatLink( cat ) --cat == 'Blah' (not 'Category:Blah', not '[[Category:Blah]]') if cat and cat ~= '' and testcases == false and mw.title.new(cat, 14).exists == false then return '[[Category:Pages with red-linked authority control categories]]' end return '' end function p.createRow( id, rawValues, link, links, withUid, specialCat, prefix) local faultyCat = 'Articles with faulty '..(specialCat or id)..' identifiers' if links then -- all links[] use withUid = false; no check needed local row = '' if prefix then row = row..'*'..prefix end for i, l in ipairs( links ) do if i == 1 and not prefix then row = row..'*' else row = row..'\n**' end if l then row = row..'<span class="uid">'..l..'</span>' else row = row..'<span class="error">The '..id..' id '..rawValues[i]..' is not valid.</span>'..addCat(faultyCat) end end return row..'\n' elseif link then -- All IDs that have a prefix support multiple identifiers, so prefix is not needed if withUid then return '*<span class="nowrap"><span class="uid">'..link..'</span></span>\n' end return '*<span class="nowrap">'..link..'</span>\n' end return '* <span class="error">The '..id..' id '..rawValues..' is not valid.</span>'..addCat(faultyCat)..'\n' end --[[==========================================================================]] --[[ Property formatting functions ]] --[[==========================================================================]] -- If a link has a suitable entry in the global inter-wiki prefix table at [[:m:Interwiki_map]], -- please consider routing through this prefix rather than as external link URL. -- This will ease future maintenance as necessary updates to the link can be centrally carried out there rather than by updating this module. -- The "external link" icon would disappear for such entries. function p.aagLink( id, label) --P3372's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[https://www.aucklandartgallery.com/explore-art-and-ideas/artist/'..id..'/ '..(label or 'Auckland')..']'..p.getCatForId( 'AAG' ) end function p.acmLink( id, label ) --P864's format regex: \d{11} (e.g. 12345678901) if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d$' ) then return false end return '[https://dl.acm.org/profile/'..id..' '..(label or 'Association for Computing Machinery')..']'..p.getCatForId( 'ACM-DL' ) end function p.adbLink( id, label ) --P1907's format regex: [a-z][-a-z]+-([1-3]\d|[1-9])\d{0,3} (e.g. barton-sir-edmund-toby-71) if not id:match( '^[a-z][-a-z]+-[1-3]%d%d?%d?%d?$' ) and not id:match( '^[a-z][-a-z]+-[1-9]%d?%d?%d?$' ) then return false end return '[http://adb.anu.edu.au/biography/'..id..' '..(label or 'Australia')..']'..p.getCatForId( 'ADB' ) end function p.admiraltyLink(id,label) --P3562's format regex: [A-Q]\d{4}(\.\d+)? (e.g. D1204.1) if not id:match('^[A-Q]%d%d%d%d$') and not id:match('^[A-Q]%d%d%d%d%.%d+$') then return false end return id..p.getCatForId( 'admiralty' ) end function p.agsaLink( id, label ) --P6804's format regex: [1-9]\d* (e.g. 3625) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://www.agsa.sa.gov.au/collection-publications/collection/creators/_/'..id..'/ '..(label or 'South Australia')..']'..p.getCatForId( 'AGSA' ) end function p.ARLHSLink(id,label) --P2980's format regex: [A-Z]{3}\d{3,4}[A-Z]?| e.g. LAT023 if not id:match('^[A-Z][A-Z][A-Z]%d%d%d%d?[A-Z]?$') then return false end return '[http://wlol.arlhs.com/lighthouse/'..id..'.html '..(label or 'ARLHS')..']'..p.getCatForId( 'ARLHS' ) end function p.autoresuyLink( id, label ) --P2558's format regex: [1-9]\d{0,4} (e.g. 12345) if not id:match( '^[1-9]%d?%d?%d?%d?$' ) then return false end return '[https://autores.uy/autor/'..id..' '..(label or 'Uruguay')..']'..p.getCatForId( 'autores.uy' ) end function p.awrLink( id, label ) --P4186's format regex: (([A-Z]{3}\d{4})|([A-Z]{2}\d{5}))[a-z] (e.g. PR00768b) if not id:match( '^[A-Z][A-Z][A-Z]%d%d%d%d[a-z]$' ) and not id:match( '^[A-Z][A-Z]%d%d%d%d%d[a-z]$' ) then return false end return '[http://www.womenaustralia.info/biogs/'..id..'.htm '..(label or 'Australian Women\'s Register')..']'..p.getCatForId( 'AWR' ) end function p.bibsysLink( id, label ) --P1015's format regex: [1-9]\d* or [1-9](\d{0,8}|\d{12}) (e.g. 1234567890123) --TODO: follow up @ [[d:Property talk:P1015#Discrepancy between the 2 regex constraints]] or escalate/investigate if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) and not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d$' ) then return false end return '[https://authority.bibsys.no/authority/rest/authorities/html/'..id..' '..(label or 'Norway')..']'..p.getCatForId( 'BIBSYS' ) end function p.bildLink( id, label ) --P2092's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[https://www.bildindex.de/document/obj'..id..' '..(label or 'Bildindex (Germany)')..']'..p.getCatForId( 'Bildindex' ) end function p.bncLink( id, label ) --P1890's format regex: \d{9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return false end return '[http://www.bncatalogo.cl/F?func=direct&local_base=red10&doc_number='..id..' '..(label or 'Chile')..']'..p.getCatForId( 'BNC' ) end function p.bneLink( id, label ) --P950's format regex: (XX|FF|a)\d{4,7}|(bima|bimo|bica|bis[eo]|bivi|Mise|Mimo|Mima)\d{10} (e.g. XX1234567) if not id:match( '^[XF][XF]%d%d%d%d%d?%d?%d?$' ) and not id:match( '^a%d%d%d%d%d?%d?%d?$' ) and not id:match( '^bi[mcsv][aoei]%d%d%d%d%d%d%d%d%d%d$' ) and not id:match( '^Mi[sm][eoa]%d%d%d%d%d%d%d%d%d%d$' ) then return false end return '[http://catalogo.bne.es/uhtbin/authoritybrowse.cgi?action=display&authority_id='..id..' '..(label or 'Spain')..']'..p.getCatForId( 'BNE' ) --no https as of 9/2019 end function p.bnfLink( id, label ) --P268's format regex: \d{8}[0-9bcdfghjkmnpqrstvwxz] (e.g. 123456789) if not id:match( '^c?b?%d%d%d%d%d%d%d%d[0-9bcdfghjkmnpqrstvwxz]$' ) then return false end --Add cb prefix if it has been removed if not id:match( '^cb.+$' ) then id = 'cb'..id end return '[https://catalogue.bnf.fr/ark:/12148/'..id..' '..(label or 'France')..'] [https://data.bnf.fr/ark:/12148/'..id..' (data)]'..p.getCatForId( 'BNF' ) end function p.bnmmLink( id, label ) --P3788's format regex: \d{9} (e.g. 000024044) if id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return '[https://catalogo.bn.gov.ar/F/?func=direct&local_base=BNA10&doc_number='..id..' '..(label or 'Argentina')..']'..p.getCatForId( 'BNMM' ) else return false end end function p.botanistLink( id, label ) --P428's format regex: ('t )?(d')?(de )?(la )?(van (der )?)?(Ma?c)?(De)?(Di)?\p{Lu}?C?['\p{Ll}]*([-'. ]*(van )?(y )?(d[ae][nr]?[- ])?(Ma?c)?[\p{Lu}bht]?C?['\p{Ll}]*)*\.? ?f?\.? (e.g. L.) --not easily/meaningfully implementable in Lua's regex since "(this)?" is not allowed... if not mw.ustring.match( id, "^[%u%l%d%. '-]+$" ) then --better than nothing return false end id = id:gsub(' +', '%%20') return '[https://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation='..id..' '..(label or 'International Plant Names Index')..']'..p.getCatForId( 'Botanist' ) end function p.bpnLink( id, label ) --P651's format regex: \d{6,8} (e.g. 00123456) if not id:match( '^%d%d%d%d%d%d%d%d$' ) and --original format regex, changed 8/2019 to not id:match( '^0?%d%d%d%d%d%d%d$' ) and --allow 1-2 leading 0s, allowed by the website not id:match( '^0?0?%d%d%d%d%d%d$' ) then return false end return '[http://www.biografischportaal.nl/en/persoon/'..id..' '..(label or 'Netherlands')..']'..p.getCatForId( 'BPN' ) --no https as of 9/2019 end function p.canticLink( id, label ) --P1273's format regex: a\d{7}[0-9x] (e.g. a10640745) if not id:match( '^a%d%d%d%d%d%d%d[%dx]$' ) then return false end return '[http://cantic.bnc.cat/registres/CUCId/'..id..' '..(label or 'Catalonia')..']'..p.getCatForId( 'CANTIC' ) --no https as of 10/2019 end function p.canticnLink( id, label ) --P9984's format regex: 981(0|1)\d{9}06706 (e.g. 981058515460906706) if not id:match( '^981[0-1]%d%d%d%d%d%d%d%d%d06706$' ) then return false end return '[https://cantic.bnc.cat/registre/'..id..' '..(label or 'Catalonia')..']'..p.getCatForId( 'CANTICN' ) end function p.ccgLink( id, label ) --P3920's format regex: ([NAIP])?[1-9]\d*(\.\d+)? (e.g. A1761) if not id:match( '^[NAIP]?[1-9]%d*$' ) and not id:match( '^[NAIP]?[1-9]%d*%.%d+$' ) then return false end return id..p.getCatForId( 'CCG' ) end function p.ciniiLink( id, label ) --P271's format regex: DA\d{7}[\dX] (e.g. DA12345678) if not id:match( '^DA%d%d%d%d%d%d%d[%dX]$' ) then return false end return '[https://ci.nii.ac.jp/author/'..id..'?l=en '..(label or 'CiNii (Japan)')..']'..p.getCatForId( 'CINII' ) end function p.cwgcLink( id, label ) --P1908's format regex: [1-9]\d* (e.g. 75228351) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://www.cwgc.org/find-war-dead/casualty/'..id..'/ '..(label or 'Commonwealth War Graves Commission')..']'..p.getCatForId( 'CWGC' ) end function p.emuLink( id, label ) --P4613's format regex: \d{1,6} (e.g. 15409 (or 015409)) if not id:match( '^%d%d?%d?%d?%d?%d?$' ) then return false end return '[http://esu.com.ua/search_articles.php?id='..id..' '..(label or 'Ukraine')..']'..p.getCatForId( 'EMU' ) end function p.daaoLink( id, label ) --P1707's format regex: [a-z\-]+\d* (e.g. rolf-harris) if not id:match( '^[a-z%-]+%d*$' ) then return false end return '[https://www.daao.org.au/bio/'..id..' '..(label or 'Australian Artists')..']'..p.getCatForId( 'DAAO' ) end function p.dblpLink( id, label ) --P2456's format regex: \d{2,3} /\d+(-\d+)?|[a-z] /[a-zA-Z][0-9A-Za-z]*(-\d+)? (e.g. 123/123) if not id:match( '^%d%d%d?/%d+$' ) and not id:match( '^%d%d%d?/%d+%-%d+$' ) and not id:match( '^[a-z]/[a-zA-Z][0-9A-Za-z]*$' ) and not id:match( '^[a-z]/[a-zA-Z][0-9A-Za-z]*%-%d+$' ) then return false end return '[https://dblp.org/pid/'..id..' '..(label or 'DBLP (computer science)')..']'..p.getCatForId( 'DBLP' ) end function p.dibLink( id, label ) --P6829's format regex: 0[01]\d{4}(\.[A-D])? (e.g. 001953) if not id:match( '^0[01]%d%d%d%d%.?[A-D]?$' ) then return false end return '[https://dib.cambridge.org/viewReadPage.do?articleId='..id..' '..(label or 'Ireland')..']'..p.getCatForId( 'DIB' ) end function p.dsiLink( id, label ) --P2349's format regex: [1-9]\d* (e.g. 1538) if not id:match( '^[1-9]%d*$' ) then return false end return '[http://www.uni-stuttgart.de/hi/gnt/dsi2/index.php?table_name=dsi&function=details&where_field=id&where_value='..id..' '..(label or 'Scientific illustrators')..']'..p.getCatForId( 'DSI' ) end function p.dtbioLink( id, label ) --P7902's format regex: 1[0-9]{7,8}[0-9X] (e.g. 118554700) if not id:match( '^1[0-9]%d%d%d%d%d%d%d?[0-9X]$' ) then return false end return '[https://www.deutsche-biographie.de/pnd'..id..'.html?language=en '..(label or 'Germany')..']'..p.getCatForId( 'DTBIO' ) end function p.fastLink( id, label ) --P2163's format regex: [1-9]\d{0,7} (e.g. 1916996) if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[http://id.worldcat.org/fast/'..id..'/ '..(label or 'Faceted Application of Subject Terminology')..']'..p.getCatForId( 'FAST' ) end function p.fnzaLink( id, label ) --P6792's format regex: [1-9]\d* (e.g. 9785) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://findnzartists.org.nz/artist/'..id..'/ '..(label or 'New Zealand Artists')..']'..p.getCatForId( 'FNZA' ) end function p.gndLink( id, label ) --P227's format regex: 1[012]?\d{7}[0-9X]|[47]\d{6}-\d|[1-9]\d{0,7}-[0-9X]|3\d{7}[0-9X] (e.g. 4079154-3) if not id:match( '^1[012]?%d%d%d%d%d%d%d[0-9X]$' ) and not id:match( '^[47]%d%d%d%d%d%d%-%d$' ) and not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%-[0-9X]$' ) and not id:match( '^3%d%d%d%d%d%d%d[0-9X]$' ) then return false end return '[https://d-nb.info/gnd/'..id..' '..(label or 'Germany')..']'..p.getCatForId( 'GND' ) end function p.googleLink( id, label ) --P1960's format regex: [-_0-9A-Za-z]{12} (e.g. CUO0vDcAAAAJ) if not id:match( '^[%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u]$' ) then return false end return '[https://scholar.google.com/citations?user='..id..' '..(label or 'Google Scholar')..']'..p.getCatForId( 'Google Scholar' ) end function p.hdsLink( id, label ) --P902's format regex: \d{6} (e.g. 050123) if not id:match( '^%d%d%d%d%d%d$' ) then return false end return '[https://hls-dhs-dss.ch/fr/articles/'..id..' '..(label or 'Historical Dictionary of Switzerland')..']'..p.getCatForId( 'HDS' ) end function p.iaafLink( id, label ) --P1146's format regex: [0-9][0-9]* (e.g. 012) if not id:match( '^%d+$' ) then return false end return '[https://www.iaaf.org/athletes/_/'..id..' '..(label or 'World Athletics')..']'..p.getCatForId( 'IAAF' ) end function p.iccuLink( id, label ) --P396's format regex: \D{2}[A-Z0-3]V\d{6} (e.g. CFIV000163) if not id:match( '^%u%u[%u0-3]V%d%d%d%d%d%d$' ) then --legacy: %u used here instead of %D (but the faulty ID cat is empty, out of ~12k uses) return false end return '[https://opac.sbn.it/nome/'..id..' '..(label or 'Italy')..']'..p.getCatForId( 'ICCU' ) end function p.iciaLink( id, label ) --P1736's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[https://www.imj.org.il/artcenter/newsite/en/?artist='..id..' '..(label or 'ICIA (Israel)')..']'..p.getCatForId( 'ICIA' ) end function p.ieuLink( id, label ) --P9070's format regex: [A-Z]\\[A-Z]\\[A-Za-z0-9]+ (e.g. K\Y\Kyiv) if not id:match( '^[A-Z]\\[A-Z]\\%w+$' ) then return false end return '[http://www.encyclopediaofukraine.com/display.asp?linkpath=pages\\'..id..' '..(label or 'Internet Encyclopedia of Ukraine')..']'..p.getCatForId( 'IEU' ) end function p.isniLink( id, label ) id = p.validateIsni( id ) --e.g. 0000-0000-6653-4145 if not id then return false end return '[https://isni.org/isni/'..id..' '..(label or 'ISNI')..']'..p.getCatForId( 'ISNI' ) end function p.j9uLink( id, label ) --P8189's format regex: 9870(0|1)\d{8}05171 (e.g. 987007305652505171) if not id:match( '^9870[0-1]%d%d%d%d%d%d%d%d05171$' ) then return false end return '[http://uli.nli.org.il/F/?func=find-b&local_base=NLX10&find_code=UID&request='..id..' '..(label or 'Israel')..']'..p.getCatForId( 'J9U' ) end function p.jocondeLink( id, label ) --P347's format regex: [\-0-9A-Za-z]{11} (e.g. 12345678901) local regex = '^'..string.rep('[%-0-9A-Za-z]', 11)..'$' if not id:match( regex ) then return false end return '[https://www.pop.culture.gouv.fr/notice/joconde/'..id..' '..(label or 'Joconde (France)')..']'..p.getCatForId( 'Joconde' ) end function p.kulturnavLink( id, label ) --P1248's format regex: [0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end return '[http://kulturnav.org/'..id..' '..(label or 'KulturNav (Norway)')..']'..p.getCatForId( 'KULTURNAV' ) --no https as of 9/2019 end function p.lccnLink( id, label ) local parts = p.splitLccn( id ) --e.g. n78039510 if not parts then return false end local lccnType = parts[1] ~= 'sh' and 'names' or 'subjects' id = parts[1] .. parts[2] .. p.append( parts[3], '0', 6 ) return '[https://id.loc.gov/authorities/'..lccnType..'/'..id..' '..(label or 'United States')..']'..p.getCatForId( 'LCCN' ) end function p.lirLink( id, label ) --P886's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[http://www.e-lir.ch/e-LIR___Lexicon.'..id..'.450.0.html '..(label or 'Lexicon Istoric Retic (Switzerland)')..']'..p.getCatForId( 'LIR' ) --no https as of 9/2019 end function p.lnbLink( id, label ) --P1368's format regex: \d{9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return false end return '[https://kopkatalogs.lv/F?func=direct&local_base=lnc10&doc_number='..id..'&P_CON_LNG=ENG '..(label or 'Latvia')..']'..p.getCatForId( 'LNB' ) end function p.marinaMilitareLink( id, label ) --P3863's format regex: [1-9]\d* (e.g. 3856) if id:match( '^[1-9]%d*$' ) then return '[http://www.marina.difesa.it/cosa-facciamo/per-la-difesa-sicurezza/fari/Pagine/'..id..'.aspx '..(label or 'Italy')..']'..p.getCatForId( 'Marina Militare' ) else return false end end function p.mathsnLink( id, label ) --P4955's format regex: [1-9]\d{4,6} (e.g. 175270) if not id:match( '^[1-9]%d%d%d%d%d?%d?$' ) then return false end return '[https://mathscinet.ams.org/mathscinet/MRAuthorID/'..id..' '..(label or 'MathSciNet')..']'..p.getCatForId( 'MATHSN' ) end function p.mbaLink( id, label ) --P434's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/artist/'..id local cat = p.getCatForId( 'MusicBrainz' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBA (identifier)|MusicBrainz]] ['..url..' artist]'..cat end end function p.mbareaLink( id, label ) --P982's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/area/'..id local cat = p.getCatForId( 'MusicBrainz area' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBAREA (identifier)|MusicBrainz]] ['..url..' area]'..cat end end function p.mbiLink( id, label ) --P1330's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/instrument/'..id local cat = p.getCatForId( 'MusicBrainz instrument' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBI (identifier)|MusicBrainz]] ['..url..' instrument]'..cat end end function p.mblLink( id, label ) --P966's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/label/'..id local cat = p.getCatForId( 'MusicBrainz label' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBL (identifier)|MusicBrainz]] ['..url..' label]'..cat end end function p.mbpLink( id, label ) --P1004's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/place/'..id local cat = p.getCatForId( 'MusicBrainz place' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBP (identifier)|MusicBrainz]] ['..url..' place]'..cat end end function p.mbrgLink( id, label ) --P436's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/release-group/'..id local cat = p.getCatForId( 'MusicBrainz release group' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBRG (identifier)|MusicBrainz]] ['..url..' release group]'..cat end end function p.mbsLink( id, label ) --P1407's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/series/'..id local cat = p.getCatForId( 'MusicBrainz series' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBS (identifier)|MusicBrainz]] ['..url..' series]'..cat end end function p.mbwLink( id, label ) --P435's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/work/'..id local cat = p.getCatForId( 'MusicBrainz work' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBW (identifier)|MusicBrainz]] ['..url..' work]'..cat end end function p.mgpLink( id, label ) --P549's format regex: \d{1,6} (e.g. 123456) if not id:match( '^%d%d?%d?%d?%d?%d?$' ) then return false end return '[https://www.mathgenealogy.org/id.php?id='..id..' '..(label or 'Mathematics Genealogy Project')..']'..p.getCatForId( 'MGP' ) end function p.mtLink( id, label ) --P3601's format regex: \d{10} (e.g. 1000004707) if id:match( '^%d%d%d%d%d%d%d%d%d%d$' ) then return '[https://www.marinetraffic.com/en/ais/details/lights/'..id..' '..(label or 'MarineTraffic')..']'..p.getCatForId( 'MarineTraffic' ) else return false end end function p.naraLink( id, label ) --P1225's format regex: ^([1-9]\d{0,8})$ (e.g. 123456789) if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[https://catalog.archives.gov/id/'..id..' '..(label or 'National Archives (US)')..']'..p.getCatForId( 'NARA' ) end function p.nclLink( id, label ) --P1048's format regex: \d+ (e.g. 1081436) if not id:match( '^%d+$' ) then return false end return '[http://aleweb.ncl.edu.tw/F/?func=accref&acc_sequence='..id..'&CON_LNG=ENG '..(label or 'Taiwan')..']'..p.getCatForId( 'NCL' ) --no https as of 9/2019 end function p.ndlLink( id, label ) --P349's format regex: 0?\d{8} (e.g. 012345678) if not id:match( '^0?%d%d%d%d%d%d%d%d$' ) then return false end return '[https://id.ndl.go.jp/auth/ndlna/'..id..' '..(label or 'Japan')..']'..p.getCatForId( 'NDL' ) end function p.ngaLink(id,label) --P3563's format rgex: 11[0-6]-\d+(\.\d+)? (e.g. 114-7721.2) if not id:match('^11[0-6]%-%d+%.?%d*$') then return false end return '[https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fmsi.nga.mil%2FqueryResults%3Fpublications%2Fngalol%2Flights-buoys%3Fvolume%3D%251%26featureNumber%3D%252%26includeRemovals%3Dfalse%26output%3Dhtml&exp=(%5Cd%7B3%7D)-(.*)&id='..id..' '..(label or 'NGA')..']'..p.getCatForId( 'NGA' ) end function p.ngvLink( id, label ) --P2041's format regex: \d+ (e.g. 12354) if not id:match( '^%d+$' ) then return false end return '[https://www.ngv.vic.gov.au/explore/collection/artist/'..id..'/ '..(label or 'Victoria')..']'..p.getCatForId( 'NGV' ) end function p.nkcLink( id, label ) --P691's format regex: [a-z]{2,4}[0-9]{2,14} (e.g. abcd12345678901234) if not id:match( '^[a-z][a-z][a-z]?[a-z]?%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[https://aleph.nkp.cz/F/?func=find-c&local_base=aut&ccl_term=ica='..id..'&CON_LNG=ENG '..(label or 'Czech Republic')..']'..p.getCatForId( 'NKC' ) end function p.nlaLink( id, label ) --P409's format regex: [1-9][0-9]{0,11} (e.g. 123456789012) if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[https://nla.gov.au/anbd.aut-an'..id..' '..(label or 'Australia')..']'..p.getCatForId( 'NLA' ) end function p.nlgLink( id, label ) --P3348's format regex: [1-9]\d* (e.g. 1) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://data.nlg.gr/resource/authority/record'..id..' '..(label or 'Greece')..']'..p.getCatForId( 'NLG' ) end function p.nlkLink( id, label ) --P5034's format regex: (KAB|KAC|KSH)([0-9]{4}|[0-9]{4}[a-zA-Z])[0-9]{4,6} (e.g. KAC201501465) if not id:match( '^KAB%d%d%d%d%a?%d%d%d%d%d?%d?$' ) and not id:match( '^KAC%d%d%d%d%a?%d%d%d%d%d?%d?$' ) and not id:match( '^KSH%d%d%d%d%a?%d%d%d%d%d?%d?$' ) then return false end return '[https://lod.nl.go.kr/resource/'..id..' '..(label or 'Korea')..']'..p.getCatForId( 'NLK' ) end function p.nlpLink( id, label ) --P1695's format regex: 9810[0-9]\d* or A[0-9]{7}[0-9X] (e.g. 9810123456789012345 or A10414836) if not id:match( '^9810%d+$' ) and not id:match( '^A%d%d%d%d%d%d%d[%dX]$' ) then return false end return '[https://tools.wmflabs.org/wikidata-externalid-url?p=1695&id='..id..' '..(label or 'Poland')..']'..p.getCatForId( 'NLP' ) end function p.nlrLink( id, label ) --P1003's format regex: \d{9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return false end return '[http://aleph.bibnat.ro:8991/F/?func=direct&local_base=NLR10&doc_number='..id..' '..(label or 'Romania')..']'..p.getCatForId( 'NLR' ) end function p.nskLink( id, label ) --P1375's format regex: \d{9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return false end return '[http://katalog.nsk.hr/F/?func=direct&doc_number='..id..'&local_base=nsk10 '..(label or 'Croatia')..']'..p.getCatForId( 'NSK' ) --no https as of 9/2019 end function p.ntaLink( id, label ) --P1006's format regex: \d{8}[\dX] (e.g. 12345678X) if not id:match( '^%d%d%d%d%d%d%d%d[%dX]$' ) then return false end return '[http://data.bibliotheken.nl/id/thes/p'..id..' '..(label or 'Netherlands')..']'..p.getCatForId( 'NTA' ) end function p.orcidLink( id, label ) id = p.validateIsni( id ) --e.g. 0000-0002-7398-5483 if not id then return false end id = id:sub( 1, 4 )..'-'..id:sub( 5, 8 )..'-'..id:sub( 9, 12 )..'-'..id:sub( 13, 16 ) return '[https://orcid.org/'..id..' '..(label or 'ORCID')..']'..p.getCatForId( 'ORCID' ) end function p.picLink( id, label ) --P2750's format regex: [1-9]\d* (e.g. 1) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://pic.nypl.org/constituents/'..id..' '..(label or 'Photographers\' Identities')..']'..p.getCatForId( 'PIC' ) end function p.plwabnLink( id, label ) --P7293's format regex: 981[0-9]{8}05606 (e.g. 9810696457305606) if not id:match( '^981%d%d%d%d%d%d%d%d05606*$' ) then return false end return '[http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=1&NU=1&IM=4&WI='..id..' '..(label or 'Poland')..']'..p.getCatForId( 'PLWABN' ) end function p.publonsLink( id, label ) --P3829's format regex: \d+ (e.g. 654601) if not id:match( '^%d+$' ) then return false end return '[https://publons.com/author/'..id..'/ '..(label or 'Publons (researchers)')..']'..p.getCatForId( 'Publons' ) end function p.ridLink( id, label ) --P1053's format regex: [A-Z]{1,3}-\d{4}-(19|20)\d\d (e.g. AAS-5150-2020) if not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-19%d%d$' ) and not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-20%d%d$' ) then return false end return '[https://www.researcherid.com/rid/'..id..' '..(label or 'ResearcherID')..']'..p.getCatForId( 'RID' ) end function p.rismLink( id, label ) --P5504's format regex: (pe|ks)?\[1-9]d* (e.g. pe30006410) if not id:match( '^pe[1-9]%d*$' ) and --99% start with 'pe' not id:match( '^ks[1-9]%d*$' ) and not id:match( '^[1-9]%d*$' ) then return false end return '[https://opac.rism.info/search?id='..id..' '..(label or 'RISM (France)')..']'..p.getCatForId( 'RISM' ) end function p.reroLink( id, label ) --P3065's format regex: 0[1-2]-[A-Z0-9]{1,10} (e.g. 02-A012345678) if not id:match( '^0[1-2]%-[A-Z%d][A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?$' ) then return false end return '[http://data.rero.ch/'..id..' '..(label or 'RERO (Switzerland)')..']'..p.getCatForId( 'RERO' ) end function p.rkdartistsLink( id, label ) --P650's format regex: [1-9]\d{0,5} (e.g. 123456) if not id:match( '^[1-9]%d?%d?%d?%d?%d?$' ) then return false end return '[https://rkd.nl/en/explore/artists/'..id..' '..(label or 'RKD Artists (Netherlands)')..']'..p.getCatForId( 'RKDartists' ) end function p.rkdidLink( id, label ) --P350's format regex: [1-9]\d{0,5} (e.g. 123456) if not id:match( '^[1-9]%d?%d?%d?%d?%d?$' ) then return false end return '[https://rkd.nl/nl/explore/images/'..id..' '..(label or 'RKD ID (Netherlands)')..']'..p.getCatForId( 'RKDID' ) end function p.rslLink( id, label ) --P947's format regex: \d{1,9} (e.g. 123456789) if not id:match( '^%d%d?%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[http://aleph.rsl.ru/F?func=find-b&find_code=SYS&adjacent=Y&local_base=RSL11&request='..id..'&CON_LNG=ENG '..(label or 'Russia')..']'..p.getCatForId( 'RSL' ) --no https as of 9/2019 end function p.scopusLink( id, label ) --P1153's format regex: [1-9]\d{9,10} (e.g. 35247902700) if not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d?$' ) then return false end return '[https://www.scopus.com/authid/detail.uri?authorId='..id..' '..(label or 'Scopus author')..']'..p.getCatForId( 'Scopus' ) end function p.selibrLink( id, label ) --P906's format regex: [1-9]\d{4,5} (e.g. 123456) if not id:match( '^[1-9]%d%d%d%d%d?$' ) then return false end return '[https://libris.kb.se/auth/'..id..' '..(label or 'Sweden')..']'..p.getCatForId( 'SELIBR' ) end function p.sikartLink( id, label ) --P781's format regex: \d{7,9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d?%d?$' ) then return false end return '[http://www.sikart.ch/KuenstlerInnen.aspx?id='..id..'&lng=en '..(label or 'SIKART (Switzerland)')..']'..p.getCatForId( 'SIKART' ) --no https as of 9/2019 end function p.snacLink( id, label ) --P3430's format regex: \d*[A-Za-z][0-9A-Za-z]* (e.g. A) if not id:match( '^%d*[A-Za-z][0-9A-Za-z]*$' ) then return false end return '[https://snaccooperative.org/ark:/99166/'..id..' '..(label or 'Social Networks and Archival Context')..']'..p.getCatForId( 'SNAC-ID' ) end function p.sudocLink( id, label ) --P269's format regex: (\d{8}[\dX]|) (e.g. 026927608) if not id:match( '^%d%d%d%d%d%d%d%d[%dxX]$' ) then --legacy: allow lowercase 'x' return false end return '[https://www.idref.fr/'..id..' '..(label or 'SUDOC (France)')..']'..p.getCatForId( 'SUDOC' ) end function p.ta98Link( id, label ) --P1323's format regex: A\d{2}\.\d\.\d{2}\.\d{3}[FM]? (e.g. A12.3.45.678) if not id:match( '^A%d%d%.%d%.%d%d%.%d%d%d[FM]?$' ) then return false end local longurl = '[http://tools.wmflabs.org/wikidata-externalid-url/?p=1323&url_prefix=https:%2F%2Fwww.unifr.ch%2Fifaa%2FPublic%2FEntryPage%2FTA98%20Tree%2FEntity%20TA98%20EN%2F&url_suffix=%20Entity%20TA98%20EN.htm&id=' return longurl..id..' '..(label or 'Terminologia Anatomica')..']'..p.getCatForId( 'TA98' ) end function p.tdviaLink( id, label ) --P7314's format regex: [0-9a-z/-]+] (e.g. barkan-omer-lutfi) if not id:match( '^[%d%l/-]+$' ) then return false end return '[https://islamansiklopedisi.org.tr/'..id..' '..(label or 'İslâm Ansiklopedisi')..']'..p.getCatForId( 'TDVİA' ) end function p.tepapaLink( id, label ) --P3544's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[https://collections.tepapa.govt.nz/agent/'..id..' '..(label or 'Te Papa (New Zealand)')..']'..p.getCatForId( 'TePapa' ) end function p.tlsLink( id, label ) id = id:gsub(' +', '_') --P1362's format regex: \p{Lu}[\p{L}\d_',\.\-\(\)\*\/–&]{3,89} (e.g. Abcd) --Mediawiki page title partial URL so consider validation with mw.title or "[^#<>%[%] {|}]" local class = "[%w_',%.%-%(%)%*%/–&]" local idlen = mw.ustring.len (id) if idlen < 4 or idlen > 90 then return false end local regex = '^%u'..string.rep(class, idlen - 1)..'$' if not mw.ustring.match( id, regex ) then return false end return '[http://tls.theaterwissenschaft.ch/wiki/'..id..' '..(label or 'Theaterlexikon (Switzerland)')..']'..p.getCatForId( 'TLS' ) --no https as of 9/2019 end function p.troveLink( id, label ) --P1315's format regex: [1-9]\d{5,7} (e.g. 12345678) if not id:match( '^[1-9]%d%d%d%d%d%d?%d?$' ) then return false end return '[https://trove.nla.gov.au/people/'..id..' '..(label or 'Trove (Australia)')..']'..p.getCatForId( 'Trove' ) end function p.ukparlLink( id, label ) --P6213's format regex: [a-zA-Z\d]{8} (e.g. AQUupyiR) if not id:match( '^[a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d]$' ) then return false end return '[https://id.parliament.uk/'..id..' '..(label or 'UK Parliament')..']'..p.getCatForId( 'UKPARL' ) end function p.ulanLink( id, label ) --P245's format regex: 500\d{6} (e.g. 500123456) if not id:match( '^500%d%d%d%d%d%d$' ) then return false end return '[https://www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid='..id..' '..(label or 'Artist Names (Getty)')..']'..p.getCatForId( 'ULAN' ) end function p.uscgLink( id, label ) --P3723's format regex: [1-7]-\d{1,5}(.[1-9])? (e.g. 6-0695) if not id:match( '^[1-7]%-%d%d?%d?%d?%d?$' ) and not id:match( '^[1-7]%-%d%d?%d?%d?%d?%.%d*[1-9]$' ) then return false end return '[[USCG (identifier)|USCG]] ([https://www.navcen.uscg.gov/pdf/lightlists/LightList%20V'..mw.ustring.sub(id,1,1)..'.pdf '..id..'])'..p.getCatForId( 'USCG' ) end function p.uscongressLink( id, label ) --P1157's format regex: [A-Z]00[01]\d{3} (e.g. A000123) if not id:match( '^[A-Z]00[01]%d%d%d$' ) then return false end return '[http://bioguide.congress.gov/scripts/biodisplay.pl?index='..id..' '..(label or 'US Congress')..']'..p.getCatForId( 'USCongress' ) --no https as of 9/2019 end function p.vcbaLink( id, label ) --P8034's format regex: \d{3}\/[1-9]\d{0,5} (e.g. 494/9793) if not id:match( '^%d%d%d\/[1-9]%d?%d?%d?%d?%d?$' ) then return false end id = id:gsub('\/', '_') return '[https://opac.vatlib.it/auth/detail/'..id..' '..(label or 'Vatican')..']'..p.getCatForId( 'VcBA' ) end function p.viafLink( id, label ) --P214's format regex: [1-9]\d(\d{0,7}|\d{17,20}) (e.g. 123456789, 1234567890123456789012) if not id:match( '^[1-9]%d%d?%d?%d?%d?%d?%d?%d?$' ) and not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d?%d?%d?$' ) then return false end -- If the "VIAF" entry at [[:m:Interwiki map]] would resolve to "https://viaf.org/viaf/$1" (rather than "http://viaf.org/viaf/$1", as it currently still does), -- then the code below could change from '[https://viaf.org/viaf/'..id..' '..id..']' to '[[:VIAF:'..id..'|'..id..']]'. return '[https://viaf.org/viaf/'..id..' '..(label or 'VIAF')..']'..p.getCatForId( 'VIAF' ) end function p.worldcatidLink( id, label ) --P7859's format regex: viaf-\d+|lccn-n[a-z]?[0-9\-]+|n[cps]-.+ (e.g. viaf-100181709, lccn-n78-95332, np-verbeck,%20william$1861) if not id:match( '^viaf%-%d+$' ) and not id:match( '^lccn%-n[a-z]?[0-9%-]+$' ) and not id:match( '^n[cps]%-.+$' ) then return false end return '[https://www.worldcat.org/identities/'..mw.uri.encode(id, 'PATH')..'/ '..(label or 'WorldCat')..']'..p.getCatForId( 'WORLDCATID' ) end function p.zbmathLink( id, label ) --P1556's format regex: [a-z][a-z\-]*(\.[a-z][a-z\-]*)?(\.[0-9]*)? (e.g. turing.alan-m) local ps = {'%l[%l%-]*', '%.%l[%l%-]*', '%.%d*'} if not id:match( '^'..ps[1]..'$' ) and -- prefix with no capture options not id:match( '^'..ps[1]..ps[2]..'$' ) and -- prefix with first capture option not id:match( '^'..ps[1]..ps[3]..'$' ) and -- prefix with second capture option not id:match( '^'..ps[1]..ps[2]..ps[3]..'$' ) then -- prefix and both capture options return false end return '[https://zbmath.org/authors/?q=ai:'..id..' '..(label or 'zbMATH')..']'..p.getCatForId( 'ZBMATH' ) end --[[=========================== Helper functions =============================]] function p.append(str, c, length) while str:len() < length do str = c..str end return str end --Returns the ISNI check digit isni must be a string where the 15 first elements are digits, e.g. 0000000066534145 function p.getIsniCheckDigit( isni ) local total = 0 for i = 1, 15 do local digit = isni:byte( i ) - 48 --Get integer value total = (total + digit) * 2 end local remainder = total % 11 local result = (12 - remainder) % 11 if result == 10 then return 'X' end return tostring( result ) end --Validate ISNI (and ORCID) and retuns it as a 16 characters string or returns false if it's invalid --See http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier function p.validateIsni( id ) --P213 (ISNI) format regex: [0-9]{4} [0-9]{4} [0-9]{4} [0-9]{3}[0-9X] (e.g. 0000-0000-6653-4145) --P496 (ORCID) format regex: 0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d{3}-\d{3}[\dX] (e.g. 0000-0002-7398-5483) id = id:gsub( '[ %-]', '' ):upper() if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d[%dX]$' ) then return false end if p.getIsniCheckDigit( id ) ~= string.char( id:byte( 16 ) ) then return false end return id end function p.splitLccn( id ) --P244's format regex: (n|nb|nr|no|ns|sh)([4-9][0-9]|00|20[0-1][0-9])[0-9]{6} (e.g. n78039510) if id:match( '^%l%l?%l?%d%d%d%d%d%d%d%d%d?%d?$' ) then id = id:gsub( '^(%l+)(%d+)(%d%d%d%d%d%d)$', '%1/%2/%3' ) end if id:match( '^%l%l?%l?/%d%d%d?%d?/%d+$' ) then return mw.text.split( id, '/' ) end return false end --[[==========================================================================]] --[[ Wikidata & documentation functions ]] --[[==========================================================================]] function p.getIdsFromWikidata( itemId, property ) local ids = {} if not mw.wikibase then return ids end local statements = mw.wikibase.getBestStatements( itemId, property ) if statements then for _, statement in ipairs( statements ) do if statement.mainsnak.datavalue then table.insert( ids, statement.mainsnak.datavalue.value ) end end end return ids end function p.checkcat( category,label ) local ret='[[:Category:'..category..'|'..label..']]' if mw.title.new(category, 14).exists == false then ret = ret..' <span class="plainlinks" style="font-size:85%;">&#91;['..tostring(mw.uri.fullUrl('Category:'..category,'action=edit&preload=Template:Authority_control/preload'))..' create]&#93;</span>' end return ret end -- Creates a human-readable standalone wikitable version of p.conf, and tracking categories with page counts, for use in the documentation function p.docConfTable( frame ) local wikiTable = '<table class="wikitable sortable">'.. '<tr><th rowspan=2>Parameter</th>'.. '<th rowspan=2>Section</th>'.. '<th rowspan=2>Appears as</th>'.. '<th rowspan=2 data-sort-type=number>Wikidata property</th>'.. '<th colspan=2>Tracking categories and page counts</th></tr>'.. '<tr><th>[[:Category:Articles with authority control information|Articles]]</th>'.. '<th>[[:Category:Articles with faulty authority control information|Faulty IDs]]</th></tr>' local lang = mw.getContentLanguage() local a, f, P = 0, 0, 0 --cumulative sums for _, conf in pairs( p.conf ) do local param, pid, section = conf[1], conf[2], conf[4] local appearsAs if conf.prefix then appearsAs = conf.prefix else appearsAs = conf[3](conf[5]) end local link = conf.link or param..' (identifier)' local category = conf.category or param local args = { id = 'f', pid } local wpl = frame:expandTemplate{ title = 'Wikidata property link', args = args } --cats local articleCat = 'Articles with '..category..' identifiers' local faultyCat = 'Articles with faulty '..category..' identifiers' --counts local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') ) local faultyCount = lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, 'pages') ) --calcs P = P + 1 --property count a = a + lang:parseFormattedNumber(articleCount) f = f + lang:parseFormattedNumber(faultyCount) --concat wikiTable = wikiTable..'<tr><td>[['..link..'|'..param..']]</td>'.. '<td>'..section..'</td>'.. '<td>'..appearsAs..'</td>'.. '<td data-sort-value='..pid..'>'..wpl..'</td>'.. '<td style="text-align: right;">'..p.checkcat(articleCat,articleCount)..'</td>'.. '<td style="text-align: right;">'..p.checkcat(faultyCat,faultyCount)..'</td></tr>' end --append derivative WorldCat cats local wcd = { 'WorldCat-LCCN', 'WorldCat-VIAF' } for _, w in pairs(wcd) do local articleCat = 'Articles with '..w..' identifiers' local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') ) local appearsAs if w == 'WorldCat-LCCN' then appearsAs = '[https://www.worldcat.org/identities/lccn-n79-113947 WorldCat (via Library of Congress)]' else appearsAs = '[https://www.worldcat.org/identities/containsVIAFID/12345789 WorldCat (via VIAF)]' end a = a + lang:parseFormattedNumber(articleCount) wikiTable = wikiTable..'<tr><td>-</td>'.. '<td>General</td>'.. '<td>'..appearsAs..'</td>'.. '<td data-sort-value='..w..'>—</td>'.. '<td style="text-align: right;">[[:Category:'..articleCat..'|'..articleCount..']]</td>'.. '<td style="text-align: right;">—</td></tr>' end --append sums wikiTable = wikiTable..'<tr><th style="text-align: right;" colspan=3>Totals</th>'.. '<th style="text-align: right;">'..lang:formatNum(P)..'</th>'.. '<th style="text-align: right;">'..lang:formatNum(a)..'</th>'.. '<th style="text-align: right;">'..lang:formatNum(f)..'</th></tr></table>' return require('Module:Suppress categories').main(wikiTable) end --[[==========================================================================]] --[[ Configuration ]] --[[==========================================================================]] -- Please use "<parameter> (identifier)" redirects rather than linking directly to the target page. -- This reduces clutter in "What links here" on both the redirect and the target, -- and improves reverse lookup of articles where a manifestation of each identifier is used. -- p.conf table basic format: { 'parameter name', propertyId # in Wikidata, formatting/validation function, section, example ID for documentation } -- p.conf table optional named parameters: -- link: to override the link in the documentation (defaults to "<parameter> (identifer)") -- category: to override the ID in category names (defaults to "... with <parameter> identifiers") -- prefix: to include a prefix (usually a wikilink explaining what the identifier is) before the external link itself p.conf = { { 'AAG', 3372, p.aagLink, 'Art galleries and museums', '1' }, { 'ACM-DL', 864, p.acmLink, 'Scientific databases', '12345678901', link = 'ACM DL (identifier)' }, { 'ADB', 1907, p.adbLink,'Biographical dictionaries', 'barton-sir-edmund-toby-71' }, { 'admiralty', 3562, p.admiraltyLink, 'Lighthouse identifiers', 'D1204.1', prefix='[[Admiralty number|Admiralty]]'}, { 'AGSA', 6804, p.agsaLink, 'Art galleries and museums', '3625' }, { 'ARLHS', 2980, p.ARLHSLink, 'Lighthouse identifiers', 'LAT023'}, { 'autores.uy', 2558, p.autoresuyLink, 'Biographical dictionaries', '12345' }, { 'AWR', 4186, p.awrLink, 'Biographical dictionaries', 'PR00768b' }, { 'BIBSYS', 1015, p.bibsysLink, 'National libraries', '1234567890123' }, { 'Bildindex', 2092, p.bildLink, 'Art research institutes', '1' }, { 'BNC', 1890, p.bncLink, 'National libraries', '123456789' }, { 'BNE', 950, p.bneLink, 'National libraries', 'XX1234567' }, { 'BNF', 268, p.bnfLink, 'National libraries', '123456789' }, { 'BNMM', 3788, p.bnmmLink, 'National libraries', '000024044' }, { 'Botanist', 428, p.botanistLink , 'Scientific databases', 'L.' }, { 'BPN', 651, p.bpnLink , 'Biographical dictionaries', '12345678' }, { 'CANTIC', 1273, p.canticLink, 'National libraries', 'a12345678' }, { 'CANTICN', 9984, p.canticnLink, 'National libraries', '981058515460906706' }, { 'CCG', 3920, p.ccgLink, 'Lighthouse identifiers', 'A1761', prefix='[[CCG (identifier)|CCG]]' }, { 'CINII', 271, p.ciniiLink, 'Scientific databases', 'DA12345678', link = 'CiNii (identifier)' }, { 'CWGC', 1908, p.cwgcLink, 'Other', '1234567' }, { 'DAAO', 1707, p.daaoLink, 'Art research institutes', 'rolf-harris' }, { 'DBLP', 2456, p.dblpLink, 'Scientific databases', '123/123' }, { 'DIB', 6829, p.dibLink, 'Biographical dictionaries', '001953' }, { 'DSI', 2349, p.dsiLink, 'Art research institutes', '1538' }, { 'DTBIO', 7902, p.dtbioLink, 'Biographical dictionaries', '118554700' }, { 'EMU', 4613, p.emuLink, 'National libraries', '15409' }, { 'FAST', 2163, p.fastLink, 'Other', '1' }, { 'FNZA', 6792, p.fnzaLink, 'Art research institutes', '12' }, { 'GND', 227, p.gndLink, 'National libraries', '4079154-3' }, { 'Google Scholar', 1960, p.googleLink, 'Scientific databases', 'QPdLuj8AAAAJ' }, { 'HDS', 902, p.hdsLink, 'Other', '050123' }, { 'IAAF', 1146, p.iaafLink, 'Other', '123' }, { 'ICCU', 396, p.iccuLink, 'National libraries', 'CFIV000163' }, --formerly SBN { 'ICIA', 1736, p.iciaLink, 'Art research institutes', '1' }, { 'IEU', 9070, p.ieuLink, 'Other', 'N\\A\\NationalAcademyofArtandArchitecture' }, { 'ISNI', 213, p.isniLink, 'General', '0000-0000-6653-4145', prefix = '[[ISNI (identifier)|ISNI]]' }, { 'J9U', 8189, p.j9uLink, 'National libraries', '987007305652505171' }, { 'Joconde', 347, p.jocondeLink, 'Art research institutes', '12345678901' }, { 'KULTURNAV', 1248, p.kulturnavLink, 'Art research institutes', '12345678-1234-1234-1234-1234567890AB', link = 'KulturNav (identifier)' }, { 'LCCN', 244, p.lccnLink, 'National libraries', 'n78039510' }, { 'LIR', 886, p.lirLink, 'Other', '1' }, { 'LNB', 1368, p.lnbLink, 'National libraries', '123456789' }, { 'Marina Militare', 3863, p.marinaMilitareLink, 'Lighthouse identifiers', '3856' }, { 'MarineTraffic', 3601, p.mtLink, 'Lighthouse identifiers', '1000004707' }, { 'MATHSN', 4955, p.mathsnLink, 'Scientific databases', '175270' }, { 'MBA', 434, p.mbaLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz' }, --special cat name { 'MBAREA', 982, p.mbareaLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz area' }, --special cat name { 'MBI', 1330, p.mbiLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz instrument' }, --special cat name { 'MBL', 966, p.mblLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz label' }, --special cat name { 'MBP', 1004, p.mbpLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz place' }, --special cat name { 'MBRG', 436, p.mbrgLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz release group' }, --special cat name { 'MBS', 1407, p.mbsLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz series' }, --special cat name { 'MBW', 435, p.mbwLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz work' }, --special cat name { 'MGP', 549, p.mgpLink, 'Scientific databases', '123456' }, { 'NARA', 1225, p.naraLink, 'Other', '12345678' }, { 'NCL', 1048, p.nclLink, 'National libraries', '1081436' }, { 'NDL', 349, p.ndlLink, 'National libraries', '012345678' }, { 'NGA', 3563, p.ngaLink, 'Lighthouse identifiers', '114-5592'}, { 'NGV', 2041, p.ngvLink, 'Art galleries and museums', '12354' }, { 'NKC', 691, p.nkcLink, 'National libraries', 'abcd12345678901234' }, { 'NLA', 409, p.nlaLink, 'National libraries', '123456789012' }, { 'NLG', 3348, p.nlgLink, 'National libraries', '12345678' }, { 'NLK', 5034, p.nlkLink, 'National libraries', 'KAB197000000' }, { 'NLP', 1695, p.nlpLink, 'National libraries', '9810123456789012345' }, { 'NLR', 1003, p.nlrLink, 'National libraries', '123456789' }, { 'NSK', 1375, p.nskLink, 'National libraries', '123456789' }, { 'NTA', 1006, p.ntaLink, 'National libraries', '12345678X' }, { 'ORCID', 496, p.orcidLink, 'General', '0000-0002-7398-5483', prefix = '[[ORCID (identifier)|ORCID]]' }, { 'PIC', 2750, p.picLink, 'Art research institutes', '1' }, { 'PLWABN', 7293, p.plwabnLink, 'National libraries', '9812345678905606' }, { 'Publons', 3829, p.publonsLink, 'Scientific databases', '2776255' }, { 'RID', 1053, p.ridLink, 'Scientific databases', 'A-1234-1934' }, { 'RISM', 5504, p.rismLink, 'Other', 'pe1', prefix = '[[RISM (identifier)|RISM (France)]]' }, { 'RERO', 3065, p.reroLink, 'Other', '02-A012345678', prefix = '[[RERO (identifier)|RERO (Switzerland)]]' }, { 'RKDartists', 650, p.rkdartistsLink, 'Art research institutes', '123456' }, { 'RKDID', 350, p.rkdidLink, 'Art research institutes', '123456' }, { 'RSL', 947, p.rslLink, 'National libraries', '123456789' }, { 'Scopus', 1153, p.scopusLink, 'Scientific databases', '7005487412' }, { 'SELIBR', 906, p.selibrLink, 'National libraries', '123456' }, { 'SIKART', 781, p.sikartLink, 'Art research institutes', '123456789' }, { 'SNAC-ID', 3430, p.snacLink, 'Other', 'A' }, { 'SUDOC', 269, p.sudocLink, 'Other', '026927608', prefix = '[[SUDOC (identifier)|SUDOC (France)]]' }, { 'TA98', 1323, p.ta98Link, 'Scientific databases', 'A12.3.45.678' }, { 'TDVİA', 7314, p.tdviaLink, 'Other', 'asim-b-behdele' }, { 'TePapa', 3544, p.tepapaLink, 'Art galleries and museums', '1' }, { 'TLS', 1362, p.tlsLink, 'Other', 'Abcd' }, { 'Trove', 1315, p.troveLink, 'Other', '12345678', prefix = '[[Trove (identifier)|Trove (Australia)]]' }, --formerly NLA-person { 'UKPARL', 6213, p.ukparlLink, 'Other', 'AQUupyiR' }, { 'ULAN', 245, p.ulanLink, 'Art research institutes', '500123456' }, { 'USCG', 3723, p.uscgLink, 'Lighthouse identifiers', '6-0695'}, { 'USCongress', 1157, p.uscongressLink, 'Other', 'A000123', link = 'US Congress (identifier)' }, { 'VcBA', 8034, p.vcbaLink, 'National libraries', '494/9793' }, { 'VIAF', 214, p.viafLink, 'General', '123456789', prefix = '[[VIAF (identifier)|VIAF]]' }, { 'WORLDCATID', 7859, p.worldcatidLink, 'General', 'lccn-n78-95332', link = 'WorldCat Identities (identifier)' }, { 'ZBMATH', 1556, p.zbmathLink, 'Scientific databases', 'turing.alan-m' }, } -- Legitimate aliases to p.conf, for convenience -- Format: { 'alias', 'parameter name in p.conf' } p.aliases = { { 'DNB', 'GND' }, --Deutsche Nationalbibliothek -> Gemeinsame Normdatei { 'MusicBrainz', 'MBA' }, { 'MusicBrainz artist', 'MBA' }, { 'MusicBrainz label', 'MBL' }, { 'MusicBrainz release group', 'MBRG' }, { 'MusicBrainz work', 'MBW' }, { 'SBN', 'ICCU' }, --SBN alias to be deprecated at a later stage { 'TDVIA', 'TDVİA' }, --alias name without diacritics { 'tdvia', 'TDVİA' }, --lowercase variant without diacritics } -- Deprecated aliases to p.conf; tracked in [[Category:Articles with deprecated authority control identifiers]] -- Format: { 'deprecated parameter name', 'replacement parameter name in p.conf' } p.deprecated = { { 'GKD', 'GND' }, { 'PND', 'GND' }, { 'RLS', 'RSL' }, { 'SWD', 'GND' }, { 'NARA-organization', 'NARA' }, { 'NARA-person', 'NARA' }, } --[[==========================================================================]] --[[ Main ]] --[[==========================================================================]] function p.authorityControl( frame ) local resolveEntity = require( 'Module:ResolveEntityId' ) local parentArgs = frame:getParent().args --WD IDs added here later local iParentArgs = 0 --count original/manual parent args only later local worldcatCat = '' local elementsCat = '' local multipleIdCat = '' local suppressedIdCat = '' local suppressedIdCatArts = '' local deprecatedIdCat = '' local differentOnWDCat = '' local sameOnWDCat = '' local stateCat = '' --redirect aliases to proper parameter names for _, a in pairs( p.aliases ) do local alias, param = a[1], a[2] if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[alias] then parentArgs[param] = parentArgs[alias] end end --redirect deprecated parameters to proper parameter names, and assign tracking cat for _, d in pairs( p.deprecated ) do local dep, param = d[1], d[2] if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[dep] then parentArgs[param] = parentArgs[dep] if namespace == 0 then deprecatedIdCat = '[[Category:Articles with deprecated authority control identifiers|'..dep..']]' end end end --use QID= parameter for testing/example purposes only local itemId = nil if namespace ~= 0 then local qid = parentArgs['qid'] or parentArgs['QID'] if qid then itemId = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '') itemId = resolveEntity._id(itemId) --nil if unresolvable end elseif mw.wikibase then itemId = mw.wikibase.getEntityIdForCurrentPage() end --Wikidata fallback if available if itemId then local suppressedIdCount = 0 local iMatches = 0 for _, params in ipairs( p.conf ) do if params[2] > 0 then local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]] if val == nil or val == '' then local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] ) if wikidataIds[1] then if val == '' and (namespace == 0 or testcases) then suppressedIdCount = suppressedIdCount + 1 suppressedIdCat = '[[Category:Articles with suppressed authority control identifiers|'..params[1]..']]' else parentArgs[params[1]] = wikidataIds[1] --add ID from WD end end else iParentArgs = iParentArgs + 1 local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] ) if wikidataIds[1] and differentOnWDCat == '' then local bMatch = false for _, wd in pairs( wikidataIds ) do if val == wd then iMatches = iMatches + 1 bMatch = true end end if bMatch == false then differentOnWDCat = '[[Category:Pages using authority control with parameters different on Wikidata|'..params[1]..']]' end end end end end if iMatches > 0 and iMatches == iParentArgs then sameOnWDCat = '[[Category:Pages using authority control with parameters all matching Wikidata]]' end if parentArgs['arts'] == 'arts' and suppressedIdCount > 0 then if namespace == 0 or testcases then local s = 's' if suppressedIdCount == 1 then s = '' end local sCat = 'ACArt with '..suppressedIdCount..' suppressed element'..s suppressedIdCatArts = addCat(sCat) end end end --configure rows local rct = 0 local sectionOrder = { 'General', 'National libraries', 'Art galleries and museums', 'Art research institutes', 'Biographical dictionaries', 'Scientific databases', 'Lighthouse identifiers', 'Other' } local sections = { ['General'] = {}, ['National libraries'] = {}, ['Art galleries and museums'] = {}, ['Art research institutes'] = {}, ['Biographical dictionaries'] = {}, ['Scientific databases'] = {}, ['Lighthouse identifiers'] = {}, ['Other'] = {} } --don't show CANTIC if CANTICN is present, since they both go to the Library of Catalonia --and the library has deprecated CANTIC IDs in favor of CANTICN IDs if parentArgs.CANTICN or parentArgs.canticn then parentArgs.CANTIC = '' parentArgs.cantic = '' end --don't show NLP if PLWABN is present, since they both go to the National Library of Poland --and the library has deprecated NLP IDs in favor of PLWABN IDs if parentArgs.PLWABN or parentArgs.plwabn then parentArgs.NLP = '' parentArgs.nlp = '' end for _, params in ipairs( p.conf ) do local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]] local tval, tlinks = {}, {} --init tables if val and val ~= '' and type(params[3]) == 'function' then table.insert( tval, val ) if params.prefix then table.insert( tlinks, params[3]( val, '1' ) ) else table.insert( tlinks, params[3]( val ) ) end end --collect other unique vals (IDs) from WD, if present if itemId and tval[1] then local nextIdVal = 2 local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] ) for _, v in pairs( wikidataIds ) do local bnew = true for _, w in pairs( tval ) do if v == w then bnew = false end end if bnew then table.insert( tval, v ) table.insert( tlinks, params[3]( v, tostring(nextIdVal) ) ) nextIdVal = nextIdVal + 1 end end end --assemble if tval[1] then table.insert( sections[params[4]], p.createRow( params[1], tval, nil, tlinks, true, params.category, params.prefix) ) rct = rct + 1 if tval[2] then multipleIdCat = p.getCatForId( 'multiple' ) end end end --WorldCat-VIAF & WorldCat-LCCN local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID'] if worldcatId == nil then --if WORLDCATID absent but unsuppressed local viafId = parentArgs['viaf'] or parentArgs['VIAF'] local lccnId = parentArgs['lccn'] or parentArgs['LCCN'] if viafId and viafId ~= '' and p.viafLink( viafId ) then --VIAF must be present, unsuppressed, & validated table.insert( sections['General'], p.createRow( 'VIAF', viafId, '[https://www.worldcat.org/identities/containsVIAFID/'..viafId..' WorldCat (via VIAF)]', nil, false ) ) if namespace == 0 then worldcatCat = '[[Category:Articles with WorldCat-VIAF identifiers]]' end rct = rct + 1 elseif lccnId and lccnId ~= '' and p.lccnLink( lccnId ) then --LCCN must be present, unsuppressed, & validated local lccnParts = p.splitLccn( lccnId ) if lccnParts and lccnParts[1] ~= 'sh' then local lccnIdFmtd = lccnParts[1]..lccnParts[2]..'-'..lccnParts[3] table.insert( sections['General'], p.createRow( 'LCCN', lccnId, '[https://www.worldcat.org/identities/lccn-'..lccnIdFmtd..' WorldCat (via Library of Congress)]', nil, false ) ) if namespace == 0 then worldcatCat = '[[Category:Articles with WorldCat-LCCN identifiers]]' end end rct = rct + 1 end end --configure Navbox local outString = '' local extrap = true local extra = parentArgs.extralist if extra == nil or extra == '' then extrap = false end if rct > 0 or extrap then local Navbox = require('Module:Navbox') local sectionID = 1 local args = { pid = 'identifiers' } -- #target the list of identifiers if testcases and itemId then args.qid = itemId end --expensive local pencil = require('Module:EditAtWikidata')._showMessage(args) local navboxArgs = { name = 'Authority control', navboxclass = 'authority-control', bodyclass = 'hlist', state = parentArgs.state or 'autocollapse', navbar = 'off' } for _, sectName in ipairs(sectionOrder) do if #sections[sectName] ~= 0 then navboxArgs['group'..sectionID] = sectName navboxArgs['list'..sectionID] = table.concat(sections[sectName]) sectionID = sectionID + 1 end end if extrap then if parentArgs.extragroup then navboxArgs['group'..sectionID] = parentArgs.extragroup else navboxArgs['group'..sectionID] = 'Additional' end navboxArgs['list'..sectionID] = extra sectionID = sectionID + 1 end if navboxArgs.list2 then navboxArgs.title = '[[Help:Authority control|Authority control]]'..pencil else local sect = navboxArgs.group1 if sect == 'General' or sect == 'Other' or sect == 'Additional' then -- Just say "Authority control" with no label if only general or only other IDs are present -- since "general" is redundant and "other" is silly when there's nothing to contrast it with navboxArgs.group1 = '[[Help:Authority control|Authority control]]'..pencil else navboxArgs.group1 = '[[Help:Authority control|Authority control: '..sect..']] '..pencil end end outString = Navbox._navbox(navboxArgs) end --auxCats if rct == 0 or rct >= 25 then if namespace == 0 or testcases then local eCat = 'AC with '..rct..' elements' elementsCat = addCat(eCat) end end if parentArgs.state then if namespace == 0 or testcases then local sCat if parentArgs.state == 'collapsed' then sCat = 'AC using state parameter: collapsed' elseif parentArgs.state == 'expanded' then sCat = 'AC using state parameter: expanded' elseif parentArgs.state == 'autocollapse' then sCat = 'AC using state parameter: autocollapse' else sCat = 'AC using state parameter: other' end stateCat = addCat(sCat) end end local auxCats = worldcatCat..elementsCat..multipleIdCat..suppressedIdCat..suppressedIdCatArts.. deprecatedIdCat..differentOnWDCat..sameOnWDCat..stateCat if testcases then auxCats = mw.ustring.gsub(auxCats, '(%[%[)(Category)', '%1:%2') --for easier checking end --out outString = outString..auxCats if namespace ~= 0 then outString = mw.ustring.gsub(outString, '(%[%[)(Category:Articles)', '%1:%2') --by definition end return outString end return p cd0db2cc5bc4d9d60808eaacdd367d8aacb169ea File:Logospaceman.png 6 28 59 2022-07-31T05:52:08Z SpaceMan 2 Uploaded own work with UploadWizard wikitext text/x-wiki =={{int:filedesc}}== {{Information |description={{en|1=Logo of the wiki}} |date=2022-07-31 |source={{own}} |author=[[User:SpaceMan|SpaceMan]] |permission= |other versions= }} =={{int:license-header}}== {{self|cc-by-sa-4.0}} bd00519072e5e85ddc30932d9abf65a3044ae7be Template:Sky/styles.css 10 166 347 2022-08-01T07:46:16Z Canopus >Ymblanter 0 Changed protection settings for "[[Template:Sky/styles.css]]": [[WP:High-risk templates|Highly visible template]]: request at [[WP:RFPP]] ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) text text/plain /* {{pp-template}} */ /* Similiar to [[Template:Coord]] styling */ .sky-coordinates-display { line-height: 1.5em; text-align: right; text-indent: 0; text-transform: none; white-space: nowrap; } body.skin-vector-legacy .sky-coordinates-display { font-size: 85%; } fb0dd75a941049acd566292c9241b00d7088d099 Module:Citation/CS1/Configuration 828 51 117 2022-08-03T21:57:10Z Canopus >Trappist the monk 0 bump pmid; Scribunto text/plain local lang_obj = mw.language.getContentLanguage(); -- make a language object for the local language; used here for languages and dates --[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E S >------------------------------ List of namespaces that should not be included in citation error categories. Same as setting notracking = true by default. Note: Namespace names should use underscores instead of spaces. ]] local uncategorized_namespaces = { 'User', 'Talk', 'User_talk', 'Wikipedia_talk', 'File_talk', 'Template_talk', 'Help_talk', 'Category_talk', 'Portal_talk', 'Book_talk', 'Draft_talk', 'Education_Program_talk', 'Module_talk', 'MediaWiki_talk' }; local uncategorized_subpages = {'/[Ss]andbox', '/[Tt]estcases', '/[^/]*[Ll]og', '/[Aa]rchive'}; -- list of Lua patterns found in page names of pages we should not categorize --[[--------------------------< M E S S A G E S >-------------------------------------------------------------- Translation table The following contains fixed text that may be output as part of a citation. This is separated from the main body to aid in future translations of this module. ]] local messages = { ['agency'] = '$1 $2', -- $1 is sepc, $2 is agency ['archived-dead'] = 'Archived from $1 on $2', ['archived-live'] = '$1 from the original on $2', ['archived-missing'] = 'Archived from the original$1 on $2', ['archived-unfit'] = 'Archived from the original on ', ['archived'] = 'Archived', ['by'] = 'By', -- contributions to authored works: introduction, foreword, afterword ['cartography'] = 'Cartography by $1', ['editor'] = 'ed.', ['editors'] = 'eds.', ['edition'] = '($1&nbsp;ed.)', ['episode'] = 'Episode $1', ['et al'] = 'et&nbsp;al.', ['in'] = 'In', -- edited works ['inactive'] = 'inactive', ['inset'] = '$1 inset', ['interview'] = 'Interviewed by $1', ['lay summary'] = 'Lay summary', ['mismatch'] = '<code class="cs1-code">&#124;$1=</code> / <code class="cs1-code">&#124;$2=</code> mismatch', -- $1 is year param name; $2 is date param name ['newsgroup'] = '[[Usenet newsgroup|Newsgroup]]:&nbsp;$1', ['notitle'] = 'No title', -- for |title=(()) and (in the future) |title=none ['original'] = 'the original', ['origdate'] = ' [$1]', ['published'] = ' (published $1)', ['retrieved'] = 'Retrieved $1', ['season'] = 'Season $1', ['section'] = '§&nbsp;$1', ['sections'] = '§§&nbsp;$1', ['series'] = '$1 $2', -- $1 is sepc, $2 is series ['seriesnum'] = 'Series $1', ['translated'] = 'Translated by $1', ['type'] = ' ($1)', -- for titletype ['written'] = 'Written at $1', ['vol'] = '$1 Vol.&nbsp;$2', -- $1 is sepc; bold journal style volume is in presentation{} ['vol-no'] = '$1 Vol.&nbsp;$2, no.&nbsp;$3', -- sepc, volume, issue (alternatively insert $1 after $2, but then we'd also have to change capitalization) ['issue'] = '$1 No.&nbsp;$2', -- $1 is sepc ['j-vol'] = '$1 $2', -- sepc, volume; bold journal volume is in presentation{} ['j-issue'] = ' ($1)', ['nopp'] = '$1 $2'; -- page(s) without prefix; $1 is sepc ['p-prefix'] = "$1 p.&nbsp;$2", -- $1 is sepc ['pp-prefix'] = "$1 pp.&nbsp;$2", -- $1 is sepc ['j-page(s)'] = ': $1', -- same for page and pages ['sheet'] = '$1 Sheet&nbsp;$2', -- $1 is sepc ['sheets'] = '$1 Sheets&nbsp;$2', -- $1 is sepc ['j-sheet'] = ': Sheet&nbsp;$1', ['j-sheets'] = ': Sheets&nbsp;$1', ['language'] = '(in $1)', ['via'] = " &ndash; via $1", ['event'] = 'Event occurs at', ['minutes'] = 'minutes in', -- Determines the location of the help page ['help page link'] = 'Help:CS1 errors', ['help page label'] = 'help', -- categories ['cat wikilink'] = '[[Category:$1]]', -- $1 is the category name [':cat wikilink'] = '[[:Category:$1|link]]', -- category name as maintenance message wikilink; $1 is the category name -- Internal errors (should only occur if configuration is bad) ['undefined_error'] = 'Called with an undefined error condition', ['unknown_ID_key'] = 'Unrecognized ID key: ', -- an ID key in id_handlers not found in ~/Identifiers func_map{} ['unknown_ID_access'] = 'Unrecognized ID access keyword: ', -- an ID access keyword in id_handlers not found in keywords_lists['id-access']{} ['unknown_argument_map'] = 'Argument map not defined for this variable', ['bare_url_no_origin'] = 'Bare URL found but origin indicator is nil or empty', ['warning_msg_e'] = '<span style="color:#d33">One or more <code style="color: inherit; background: inherit; border: none; padding: inherit;">&#123;{$1}}</code> templates have errors</span>; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).'; -- $1 is template link ['warning_msg_m'] = '<span style="color:#3a3">One or more <code style="color: inherit; background: inherit; border: none; padding: inherit;">&#123;{$1}}</code> templates have maintenance messages</span>; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).'; -- $1 is template link } --[[--------------------------< C I T A T I O N _ C L A S S _ M A P >------------------------------------------ this table maps the value assigned to |CitationClass= in the cs1|2 templates to the canonical template name when the value assigned to |CitationClass= is different from the canonical template name. |CitationClass= values are used as class attributes in the <cite> tag that encloses the citation so these names may not contain spaces while the canonical template name may. These names are used in warning_msg_e and warning_msg_m to create links to the template's documentation when an article is displayed in preivew mode. Most cs1|2 template |CitationClass= values at en.wiki match their canonical template names so are not listed here. ]] local citation_class_map_t = { -- TODO: if kept, these and all other config.CitationClass 'names' require some sort of i18n ['audio-visual'] = 'AV media', -- TODO: move to ~/Configuration ['AV-media-notes'] = 'AV media notes', ['encyclopaedia'] = 'encyclopedia', ['mailinglist'] = 'mailing list', ['pressrelease'] = 'press release' } --[=[-------------------------< E T _ A L _ P A T T E R N S >-------------------------------------------------- This table provides Lua patterns for the phrase "et al" and variants in name text (author, editor, etc.). The main module uses these to identify and emit the 'etal' message. ]=] local et_al_patterns = { "[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][%.;,\"']*$", -- variations on the 'et al' theme "[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][Ii][AaIi][Ee]?[%.;,\"']*$", -- variations on the 'et alia', 'et alii' and 'et aliae' themes (false positive 'et aliie' unlikely to match) "[;,]? *%f[%a]and [Oo]thers", -- an alternative to et al. "%[%[ *[Ee][Tt]%.? *[Aa][Ll]%.? *%]%]", -- a wikilinked form "%(%( *[Ee][Tt]%.? *[Aa][Ll]%.? *%)%)", -- a double-bracketed form (to counter partial removal of ((...)) syntax) "[%(%[] *[Ee][Tt]%.? *[Aa][Ll]%.? *[%)%]]", -- a bracketed form } --[[--------------------------< P R E S E N T A T I O N >------------------------ Fixed presentation markup. Originally part of citation_config.messages it has been moved into its own, more semantically correct place. ]] local presentation = { -- .citation-comment class is specified at Help:CS1_errors#Controlling_error_message_display ['hidden-error'] = '<span class="cs1-hidden-error citation-comment">$1</span>', ['visible-error'] = '<span class="cs1-visible-error citation-comment">$1</span>', ['hidden-maint'] = '<span class="cs1-maint citation-comment">$1</span>', ['accessdate'] = '<span class="reference-accessdate">$1$2</span>', -- to allow editors to hide accessdate using personal CSS ['bdi'] = '<bdi$1>$2</bdi>', -- bidirectional isolation used with |script-title= and the like ['cite'] = '<cite class="$1">$2</cite>'; -- for use when citation does not have a namelist and |ref= not set so no id="..." attribute ['cite-id'] = '<cite id="$1" class="$2">$3</cite>'; -- for use when when |ref= is set or when citation has a namelist ['format'] = ' <span class="cs1-format">($1)</span>', -- for |format=, |chapter-format=, etc. -- various access levels, for |access=, |doi-access=, |arxiv=, ... -- narrow no-break space &#8239; may work better than nowrap CSS. Or not? Browser support? ['ext-link-access-signal'] = '<span class="$1" title="$2">$3</span>', -- external link with appropriate lock icon ['free'] = {class='cs1-lock-free', title='Freely accessible'}, -- classes defined in Module:Citation/CS1/styles.css ['registration'] = {class='cs1-lock-registration', title='Free registration required'}, ['limited'] = {class='cs1-lock-limited', title='Free access subject to limited trial, subscription normally required'}, ['subscription'] = {class='cs1-lock-subscription', title='Paid subscription required'}, ['interwiki-icon'] = '<span class="$1" title="$2">$3</span>', ['class-wikisource'] = 'cs1-ws-icon', ['italic-title'] = "''$1''", ['kern-left'] = '<span class="cs1-kern-left"></span>$1', -- spacing to use when title contains leading single or double quote mark ['kern-right'] = '$1<span class="cs1-kern-right"></span>', -- spacing to use when title contains trailing single or double quote mark ['nowrap1'] = '<span class="nowrap">$1</span>', -- for nowrapping an item: <span ...>yyyy-mm-dd</span> ['nowrap2'] = '<span class="nowrap">$1</span> $2', -- for nowrapping portions of an item: <span ...>dd mmmm</span> yyyy (note white space) ['ocins'] = '<span title="$1" class="Z3988"></span>', ['parameter'] = '<code class="cs1-code">&#124;$1=</code>', ['ps_cs1'] = '.'; -- CS1 style postscript (terminal) character ['ps_cs2'] = ''; -- CS2 style postscript (terminal) character (empty string) ['quoted-text'] = '<q>$1</q>', -- for wrapping |quote= content ['quoted-title'] = '"$1"', ['sep_cs1'] = '.', -- CS1 element separator ['sep_cs2'] = ',', -- CS2 separator ['sep_nl'] = ';', -- CS1|2 style name-list separator between names is a semicolon ['sep_nl_and'] = ' and ', -- used as last nl sep when |name-list-style=and and list has 2 items ['sep_nl_end'] = '; and ', -- used as last nl sep when |name-list-style=and and list has 3+ names ['sep_name'] = ', ', -- CS1|2 style last/first separator is <comma><space> ['sep_nl_vanc'] = ',', -- Vancouver style name-list separator between authors is a comma ['sep_name_vanc'] = ' ', -- Vancouver style last/first separator is a space ['sep_list'] = ', ', -- used for |language= when list has 3+ items except for last sep which uses sep_list_end ['sep_list_pair'] = ' and ', -- used for |language= when list has 2 items ['sep_list_end'] = ', and ', -- used as last list sep for |language= when list has 3+ items ['trans-italic-title'] = "&#91;''$1''&#93;", ['trans-quoted-title'] = "&#91;$1&#93;", -- for |trans-title= and |trans-quote= ['vol-bold'] = '$1 <b>$2</b>', -- sepc, volume; for bold journal cites; for other cites ['vol'] in messages{} } --[[--------------------------< A L I A S E S >--------------------------------- Aliases table for commonly passed parameters. Parameter names on the right side in the assignments in this table must have been defined in the Whitelist before they will be recognized as valid parameter names ]] local aliases = { ['AccessDate'] = {'access-date', 'accessdate'}, -- Used by InternetArchiveBot ['Agency'] = 'agency', ['ArchiveDate'] = {'archive-date', 'archivedate'}, -- Used by InternetArchiveBot ['ArchiveFormat'] = 'archive-format', ['ArchiveURL'] = {'archive-url', 'archiveurl'}, -- Used by InternetArchiveBot ['ASINTLD'] = 'asin-tld', ['At'] = 'at', -- Used by InternetArchiveBot ['Authors'] = {'authors', 'people', 'credits'}, ['BookTitle'] = {'book-title', 'booktitle'}, ['Cartography'] = 'cartography', ['Chapter'] = {'chapter', 'contribution', 'entry', 'article', 'section'}, ['ChapterFormat'] = {'chapter-format', 'contribution-format', 'entry-format', 'article-format', 'section-format'}; ['ChapterURL'] = {'chapter-url', 'contribution-url', 'entry-url', 'article-url', 'section-url', 'chapterurl'}, -- Used by InternetArchiveBot ['ChapterUrlAccess'] = {'chapter-url-access', 'contribution-url-access', 'entry-url-access', 'article-url-access', 'section-url-access'}, -- Used by InternetArchiveBot ['Class'] = 'class', -- cite arxiv and arxiv identifier ['Collaboration'] = 'collaboration', ['Conference'] = {'conference', 'event'}, ['ConferenceFormat'] = 'conference-format', ['ConferenceURL'] = 'conference-url', -- Used by InternetArchiveBot ['Date'] = {'date', 'air-date', 'airdate'}, -- air-date and airdate for cite episode and cite serial only ['Degree'] = 'degree', ['DF'] = 'df', ['DisplayAuthors'] = {'display-authors', 'display-subjects'}, ['DisplayContributors'] = 'display-contributors', ['DisplayEditors'] = 'display-editors', ['DisplayInterviewers'] = 'display-interviewers', ['DisplayTranslators'] = 'display-translators', ['Docket'] = 'docket', ['DoiBroken'] = 'doi-broken-date', ['Edition'] = 'edition', ['Embargo'] = 'pmc-embargo-date', ['Encyclopedia'] = {'encyclopedia', 'encyclopaedia', 'dictionary'}, -- cite encyclopedia only ['Episode'] = 'episode', -- cite serial only TODO: make available to cite episode? ['Format'] = 'format', ['ID'] = {'id', 'ID'}, ['Inset'] = 'inset', ['Issue'] = {'issue', 'number'}, ['Language'] = {'language', 'lang'}, ['LayDate'] = 'lay-date', ['LayFormat'] = 'lay-format', ['LaySource'] = 'lay-source', ['LayURL'] = 'lay-url', ['MailingList'] = {'mailing-list', 'mailinglist'}, -- cite mailing list only ['Map'] = 'map', -- cite map only ['MapFormat'] = 'map-format', -- cite map only ['MapURL'] = {'map-url', 'mapurl'}, -- cite map only -- Used by InternetArchiveBot ['MapUrlAccess'] = 'map-url-access', -- cite map only -- Used by InternetArchiveBot ['Minutes'] = 'minutes', ['Mode'] = 'mode', ['NameListStyle'] = 'name-list-style', ['Network'] = 'network', ['Newsgroup'] = 'newsgroup', -- cite newsgroup only ['NoPP'] = {'no-pp', 'nopp'}, ['NoTracking'] = {'no-tracking', 'template-doc-demo'}, ['Number'] = 'number', -- this case only for cite techreport ['OrigDate'] = {'orig-date', 'orig-year', 'origyear'}, ['Others'] = 'others', ['Page'] = {'page', 'p'}, -- Used by InternetArchiveBot ['Pages'] = {'pages', 'pp'}, -- Used by InternetArchiveBot ['Periodical'] = {'journal', 'magazine', 'newspaper', 'periodical', 'website', 'work'}, ['Place'] = {'place', 'location'}, ['PostScript'] = 'postscript', ['PublicationDate'] = {'publication-date', 'publicationdate'}, ['PublicationPlace'] = {'publication-place', 'publicationplace'}, ['PublisherName'] = {'publisher', 'institution'}, ['Quote'] = {'quote', 'quotation'}, ['QuotePage'] = 'quote-page', ['QuotePages'] = 'quote-pages', ['Ref'] = 'ref', ['Scale'] = 'scale', ['ScriptChapter'] = {'script-chapter', 'script-contribution', 'script-entry', 'script-article', 'script-section'}, ['ScriptMap'] = 'script-map', ['ScriptPeriodical'] = {'script-journal', 'script-magazine', 'script-newspaper', 'script-periodical', 'script-website', 'script-work'}, ['ScriptQuote'] = 'script-quote', ['ScriptTitle'] = 'script-title', -- Used by InternetArchiveBot ['Season'] = 'season', ['Sections'] = 'sections', -- cite map only ['Series'] = {'series', 'version'}, ['SeriesLink'] = {'series-link', 'serieslink'}, ['SeriesNumber'] = {'series-number', 'series-no'}, ['Sheet'] = 'sheet', -- cite map only ['Sheets'] = 'sheets', -- cite map only ['Station'] = 'station', ['Time'] = 'time', ['TimeCaption'] = 'time-caption', ['Title'] = 'title', -- Used by InternetArchiveBot ['TitleLink'] = {'title-link', 'episode-link', 'episodelink'}, -- Used by InternetArchiveBot ['TitleNote'] = 'department', ['TitleType'] = {'type', 'medium'}, ['TransChapter'] = {'trans-article', 'trans-chapter', 'trans-contribution', 'trans-entry', 'trans-section'}, ['Transcript'] = 'transcript', ['TranscriptFormat'] = 'transcript-format', ['TranscriptURL'] = {'transcript-url', 'transcripturl'}, -- Used by InternetArchiveBot ['TransMap'] = 'trans-map', -- cite map only ['TransPeriodical'] = {'trans-journal', 'trans-magazine', 'trans-newspaper', 'trans-periodical', 'trans-website', 'trans-work'}, ['TransQuote'] = 'trans-quote', ['TransTitle'] = 'trans-title', -- Used by InternetArchiveBot ['URL'] = {'url', 'URL'}, -- Used by InternetArchiveBot ['UrlAccess'] = 'url-access', -- Used by InternetArchiveBot ['UrlStatus'] = 'url-status', -- Used by InternetArchiveBot ['Vauthors'] = 'vauthors', ['Veditors'] = 'veditors', ['Via'] = 'via', ['Volume'] = 'volume', ['Year'] = 'year', ['AuthorList-First'] = {"first#", "author-first#", "author#-first", "given#", "author-given#", "author#-given"}, ['AuthorList-Last'] = {"last#", "author-last#", "author#-last", "surname#", "author-surname#", "author#-surname", "author#", "subject#", 'host#'}, ['AuthorList-Link'] = {"author-link#", "author#-link", "subject-link#", "subject#-link", "authorlink#", "author#link"}, ['AuthorList-Mask'] = {"author-mask#", "author#-mask", "subject-mask#", "subject#-mask"}, ['ContributorList-First'] = {'contributor-first#', 'contributor#-first', 'contributor-given#', 'contributor#-given'}, ['ContributorList-Last'] = {'contributor-last#', 'contributor#-last', 'contributor-surname#', 'contributor#-surname', 'contributor#'}, ['ContributorList-Link'] = {'contributor-link#', 'contributor#-link'}, ['ContributorList-Mask'] = {'contributor-mask#', 'contributor#-mask'}, ['EditorList-First'] = {"editor-first#", "editor#-first", "editor-given#", "editor#-given"}, ['EditorList-Last'] = {"editor-last#", "editor#-last", "editor-surname#", "editor#-surname", "editor#"}, ['EditorList-Link'] = {"editor-link#", "editor#-link"}, ['EditorList-Mask'] = {"editor-mask#", "editor#-mask"}, ['InterviewerList-First'] = {'interviewer-first#', 'interviewer#-first', 'interviewer-given#', 'interviewer#-given'}, ['InterviewerList-Last'] = {'interviewer-last#', 'interviewer#-last', 'interviewer-surname#', 'interviewer#-surname', 'interviewer#'}, ['InterviewerList-Link'] = {'interviewer-link#', 'interviewer#-link'}, ['InterviewerList-Mask'] = {'interviewer-mask#', 'interviewer#-mask'}, ['TranslatorList-First'] = {'translator-first#', 'translator#-first', 'translator-given#', 'translator#-given'}, ['TranslatorList-Last'] = {'translator-last#', 'translator#-last', 'translator-surname#', 'translator#-surname', 'translator#'}, ['TranslatorList-Link'] = {'translator-link#', 'translator#-link'}, ['TranslatorList-Mask'] = {'translator-mask#', 'translator#-mask'}, } --[[--------------------------< P U N C T _ S K I P >--------------------------- builds a table of parameter names that the extraneous terminal punctuation check should not check. ]] local punct_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value 'BookTitle', 'Chapter', 'ScriptChapter', 'ScriptTitle', 'Title', 'TransChapter', 'Transcript', 'TransMap', 'TransTitle', -- title-holding parameters 'AuthorList-Mask', 'ContributorList-Mask', 'EditorList-Mask', 'InterviewerList-Mask', 'TranslatorList-Mask', -- name-list mask may have name separators 'PostScript', 'Quote', 'ScriptQuote', 'TransQuote', 'Ref', -- miscellaneous 'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'LayURL', 'MapURL', 'TranscriptURL', 'URL', -- URL-holding parameters } local url_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value 'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'ID', 'LayURL', 'MapURL', 'TranscriptURL', 'URL', -- parameters allowed to hold urls 'Page', 'Pages', 'At', 'QuotePage', 'QuotePages', -- insource locators allowed to hold urls } local function build_skip_table (skip_t, meta_params) for _, meta_param in ipairs (meta_params) do -- for each meta parameter key local params = aliases[meta_param]; -- get the parameter or the table of parameters associated with the meta parameter name if 'string' == type (params) then skip_t[params] = 1; -- just a single parameter else for _, param in ipairs (params) do -- get the parameter name skip_t[param] = 1; -- add the parameter name to the skip table local count; param, count = param:gsub ('#', ''); -- remove enumerator marker from enumerated parameters if 0 ~= count then -- if removed skip_t[param] = 1; -- add param name without enumerator marker end end end end return skip_t; end local punct_skip = {}; local url_skip = {}; --[[-----------< S P E C I A L C A S E T R A N S L A T I O N S >------------ This table is primarily here to support internationalization. Translations in this table are used, for example, when an error message, category name, etc., is extracted from the English alias key. There may be other cases where this translation table may be useful. ]] local is_Latn = 'A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143'; local special_case_translation = { ['AuthorList'] = 'authors list', -- used to assemble maintenance category names ['ContributorList'] = 'contributors list', -- translation of these names plus translation of the base mainenance category names in maint_cats{} table below ['EditorList'] = 'editors list', -- must match the names of the actual categories ['InterviewerList'] = 'interviewers list', -- this group or translations used by name_has_ed_markup() and name_has_mult_names() ['TranslatorList'] = 'translators list', -- Lua patterns to match pseudo-titles used by InternetArchiveBot and others as placeholder for unknown |title= value ['archived_copy'] = { -- used with CS1 maint: Archive[d] copy as title ['en'] = '^archived?%s+copy$', -- for English; translators: keep this because templates imported from en.wiki ['local'] = nil, -- translators: replace ['local'] = nil with lowercase translation only when bots or tools create generic titles in your language }, -- Lua patterns to match generic titles; usually created by bots or reference filling tools -- translators: replace ['local'] = nil with lowercase translation only when bots or tools create generic titles in your language -- generic titles and patterns in this table should be lowercase only -- leave ['local'] nil except when there is a matching generic title in your language -- boolean 'true' for plain-text searches; 'false' for pattern searches ['generic_titles'] = { ['accept'] = { }, ['reject'] = { {['en'] = {'^wayback%s+machine$', false}, ['local'] = nil}, {['en'] = {'are you a robot', true}, ['local'] = nil}, {['en'] = {'hugedomains.com', true}, ['local'] = nil}, {['en'] = {'^[%(%[{<]?no +title[>}%]%)]?$', false}, ['local'] = nil}, {['en'] = {'page not found', true}, ['local'] = nil}, {['en'] = {'subscribe to read', true}, ['local'] = nil}, {['en'] = {'^[%(%[{<]?unknown[>}%]%)]?$', false}, ['local'] = nil}, {['en'] = {'website is for sale', true}, ['local'] = nil}, {['en'] = {'^404', false}, ['local'] = nil}, {['en'] = {'internet archive wayback machine', true}, ['local'] = nil}, {['en'] = {'log into facebook', true}, ['local'] = nil}, {['en'] = {'login • instagram', true}, ['local'] = nil}, {['en'] = {'redirecting...', true}, ['local'] = nil}, {['en'] = {'usurped title', true}, ['local'] = nil}, -- added by a GreenC bot {['en'] = {'webcite query result', true}, ['local'] = nil}, {['en'] = {'wikiwix\'s cache', true}, ['local'] = nil}, } }, -- boolean 'true' for plain-text searches, search string must be lowercase only -- boolean 'false' for pattern searches -- leave ['local'] nil except when there is a matching generic name in your language ['generic_names'] = { ['accept'] = { {['en'] = {'%[%[[^|]*%(author%) *|[^%]]*%]%]', false}, ['local'] = nil}, }, ['reject'] = { {['en'] = {'about us', true}, ['local'] = nil}, {['en'] = {'%f[%a][Aa]dvisor%f[%A]', false}, ['local'] = nil}, {['en'] = {'%f[%a][Aa]uthor%f[%A]', false}, ['local'] = nil}, {['en'] = {'collaborator', true}, ['local'] = nil}, {['en'] = {'contributor', true}, ['local'] = nil}, {['en'] = {'contact us', true}, ['local'] = nil}, {['en'] = {'directory', true}, ['local'] = nil}, {['en'] = {'%f[%(%[][%(%[]%s*eds?%.?%s*[%)%]]?$', false}, ['local'] = nil}, {['en'] = {'[,%.%s]%f[e]eds?%.?$', false}, ['local'] = nil}, {['en'] = {'^eds?[%.,;]', false}, ['local'] = nil}, {['en'] = {'^[%(%[]%s*[Ee][Dd][Ss]?%.?%s*[%)%]]', false}, ['local'] = nil}, {['en'] = {'%f[%a][Ee]dited%f[%A]', false}, ['local'] = nil}, {['en'] = {'%f[%a][Ee]ditors?%f[%A]', false}, ['local'] = nil}, {['en'] = {'%f[%a]]Ee]mail%f[%A]', false}, ['local'] = nil}, {['en'] = {'facebook', true}, ['local'] = nil}, {['en'] = {'google', true}, ['local'] = nil}, {['en'] = {'home page', true}, ['local'] = nil}, {['en'] = {'instagram', true}, ['local'] = nil}, {['en'] = {'interviewer', true}, ['local'] = nil}, {['en'] = {'linkedIn', true}, ['local'] = nil}, {['en'] = {'^[Nn]ews$', false}, ['local'] = nil}, {['en'] = {'pinterest', true}, ['local'] = nil}, {['en'] = {'policy', true}, ['local'] = nil}, {['en'] = {'privacy', true}, ['local'] = nil}, {['en'] = {'translator', true}, ['local'] = nil}, {['en'] = {'tumblr', true}, ['local'] = nil}, {['en'] = {'twitter', true}, ['local'] = nil}, {['en'] = {'site name', true}, ['local'] = nil}, {['en'] = {'statement', true}, ['local'] = nil}, {['en'] = {'submitted', true}, ['local'] = nil}, {['en'] = {'super.?user', false}, ['local'] = nil}, {['en'] = {'%f['..is_Latn..'][Uu]ser%f[^'..is_Latn..']', false}, ['local'] = nil}, {['en'] = {'verfasser', true}, ['local'] = nil}, } } } --[[--------------------------< D A T E _ N A M E S >---------------------------------------------------------- This table of tables lists local language date names and fallback English date names. The code in Date_validation will look first in the local table for valid date names. If date names are not found in the local table, the code will look in the English table. Because citations can be copied to the local wiki from en.wiki, the English is required when the date-name translation function date_name_xlate() is used. In these tables, season numbering is defined by Extended Date/Time Format (EDTF) Specification (https://www.loc.gov/standards/datetime/) which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using numbers 21-41. CS1|2 only supports generic seasons. EDTF does support the distinction between north and south hemisphere seasons but CS1|2 has no way to make that distinction. 33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each) The standard does not address 'named' dates so, for the purposes of CS1|2, Easter and Christmas are defined here as 98 and 99, which should be out of the ISO 8601 (EDTF) range of uses for a while. local_date_names_from_mediawiki is a boolean. When set to: true – module will fetch local month names from MediaWiki for both date_names['local']['long'] and date_names['local']['short'] false – module will *not* fetch local month names from MediaWiki Caveat lector: There is no guarantee that MediaWiki will provide short month names. At your wiki you can test the results of the MediaWiki fetch in the debug console with this command (the result is alpha sorted): =mw.dumpObject (p.date_names['local']) While the module can fetch month names from MediaWiki, it cannot fetch the quarter, season, and named date names from MediaWiki. Those must be translated manually. ]] local local_date_names_from_mediawiki = true; -- when false, manual translation required for date_names['local']['long'] and date_names['local']['short'] -- when true, module fetches long and short month names from MediaWiki local date_names = { ['en'] = { -- English ['long'] = {['January'] = 1, ['February'] = 2, ['March'] = 3, ['April'] = 4, ['May'] = 5, ['June'] = 6, ['July'] = 7, ['August'] = 8, ['September'] = 9, ['October'] = 10, ['November'] = 11, ['December'] = 12}, ['short'] = {['Jan'] = 1, ['Feb'] = 2, ['Mar'] = 3, ['Apr'] = 4, ['May'] = 5, ['Jun'] = 6, ['Jul'] = 7, ['Aug'] = 8, ['Sep'] = 9, ['Oct'] = 10, ['Nov'] = 11, ['Dec'] = 12}, ['quarter'] = {['First Quarter'] = 33, ['Second Quarter'] = 34, ['Third Quarter'] = 35, ['Fourth Quarter'] = 36}, ['season'] = {['Winter'] = 24, ['Spring'] = 21, ['Summer'] = 22, ['Fall'] = 23, ['Autumn'] = 23}, ['named'] = {['Easter'] = 98, ['Christmas'] = 99}, }, -- when local_date_names_from_mediawiki = false ['local'] = { -- replace these English date names with the local language equivalents ['long'] = {['January'] = 1, ['February'] = 2, ['March'] = 3, ['April'] = 4, ['May'] = 5, ['June'] = 6, ['July'] = 7, ['August'] = 8, ['September'] = 9, ['October'] = 10, ['November'] = 11, ['December'] = 12}, ['short'] = {['Jan'] = 1, ['Feb'] = 2, ['Mar'] = 3, ['Apr'] = 4, ['May'] = 5, ['Jun'] = 6, ['Jul'] = 7, ['Aug'] = 8, ['Sep'] = 9, ['Oct'] = 10, ['Nov'] = 11, ['Dec'] = 12}, ['quarter'] = {['First Quarter'] = 33, ['Second Quarter'] = 34, ['Third Quarter'] = 35, ['Fourth Quarter'] = 36}, ['season'] = {['Winter'] = 24, ['Spring'] = 21, ['Summer'] = 22, ['Fall'] = 23, ['Autumn'] = 23}, ['named'] = {['Easter'] = 98, ['Christmas'] = 99}, }, ['inv_local_long'] = {}, -- used in date reformatting & translation; copy of date_names['local'].long where k/v are inverted: [1]='<local name>' etc. ['inv_local_short'] = {}, -- used in date reformatting & translation; copy of date_names['local'].short where k/v are inverted: [1]='<local name>' etc. ['inv_local_quarter'] = {}, -- used in date translation; copy of date_names['local'].quarter where k/v are inverted: [1]='<local name>' etc. ['inv_local_season'] = {}, -- used in date translation; copy of date_names['local'].season where k/v are inverted: [1]='<local name>' etc. ['inv_local_named'] = {}, -- used in date translation; copy of date_names['local'].named where k/v are inverted: [1]='<local name>' etc. ['local_digits'] = {['0'] = '0', ['1'] = '1', ['2'] = '2', ['3'] = '3', ['4'] = '4', ['5'] = '5', ['6'] = '6', ['7'] = '7', ['8'] = '8', ['9'] = '9'}, -- used to convert local language digits to Western 0-9 ['xlate_digits'] = {}, } if local_date_names_from_mediawiki then -- if fetching local month names from MediaWiki is enabled local long_t = {}; local short_t = {}; for i=1, 12 do -- loop 12x and local name = lang_obj:formatDate('F', '2022-' .. i .. '-1'); -- get long month name for each i long_t[name] = i; -- save it name = lang_obj:formatDate('M', '2022-' .. i .. '-1'); -- get short month name for each i short_t[name] = i; -- save it end date_names['local']['long'] = long_t; -- write the long table – overwrites manual translation date_names['local']['short'] = short_t; -- write the short table – overwrites manual translation end -- create inverted date-name tables for reformatting and/or translation for _, invert_t in pairs {{'long', 'inv_local_long'}, {'short', 'inv_local_short'}, {'quarter', 'inv_local_quarter'}, {'season', 'inv_local_season'}, {'named', 'inv_local_named'}} do for name, i in pairs (date_names['local'][invert_t[1]]) do -- this table is ['name'] = i date_names[invert_t[2]][i] = name; -- invert to get [i] = 'name' for conversions from ymd end end for ld, ed in pairs (date_names.local_digits) do -- make a digit translation table for simple date translation from en to local language using local_digits table date_names.xlate_digits [ed] = ld; -- en digit becomes index with local digit as the value end local df_template_patterns = { -- table of redirects to {{Use dmy dates}} and {{Use mdy dates}} '{{ *[Uu]se +(dmy) +dates *[|}]', -- 1159k -- sorted by approximate transclusion count '{{ *[Uu]se +(mdy) +dates *[|}]', -- 212k '{{ *[Uu]se +(MDY) +dates *[|}]', -- 788 '{{ *[Uu]se +(DMY) +dates *[|}]', -- 343 '{{ *([Mm]dy) *[|}]', -- 176 '{{ *[Uu]se *(dmy) *[|}]', -- 156 + 18 '{{ *[Uu]se *(mdy) *[|}]', -- 149 + 11 '{{ *([Dd]my) *[|}]', -- 56 '{{ *[Uu]se +(MDY) *[|}]', -- 5 '{{ *([Dd]MY) *[|}]', -- 3 '{{ *[Uu]se(mdy)dates *[|}]', -- 1 '{{ *[Uu]se +(DMY) *[|}]', -- 0 '{{ *([Mm]DY) *[|}]', -- 0 } local function get_date_format () local title_object = mw.title.getCurrentTitle(); if title_object.namespace == 10 then -- not in template space so that unused templates appear in unused-template-reports; return nil; -- auto-formatting does not work in Template space so don't set global_df end local content = title_object:getContent() or ''; -- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625 for _, pattern in ipairs (df_template_patterns) do -- loop through the patterns looking for {{Use dmy dates}} or {{Use mdy dates}} or any of their redirects local start, _, match = content:find(pattern); -- match is the three letters indicating desired date format if match then content = content:match ('%b{}', start); -- get the whole template if content:match ('| *cs1%-dates *= *[lsy][sy]?') then -- look for |cs1-dates=publication date length access-/archive-date length return match:lower() .. '-' .. content:match ('| *cs1%-dates *= *([lsy][sy]?)'); else return match:lower() .. '-all'; -- no |cs1-dates= k/v pair; return value appropriate for use in |df= end end end end local global_df; --[[-----------------< V O L U M E , I S S U E , P A G E S >------------------ These tables hold cite class values (from the template invocation) and identify those templates that support |volume=, |issue=, and |page(s)= parameters. Cite conference and cite map require further qualification which is handled in the main module. ]] local templates_using_volume = {'citation', 'audio-visual', 'book', 'conference', 'encyclopaedia', 'interview', 'journal', 'magazine', 'map', 'news', 'report', 'techreport', 'thesis'} local templates_using_issue = {'citation', 'conference', 'episode', 'interview', 'journal', 'magazine', 'map', 'news', 'podcast'} local templates_not_using_page = {'audio-visual', 'episode', 'mailinglist', 'newsgroup', 'podcast', 'serial', 'sign', 'speech'} --[[ These tables control when it is appropriate for {{citation}} to render |volume= and/or |issue=. The parameter names in the tables constrain {{citation}} so that its renderings match the renderings of the equivalent cs1 templates. For example, {{cite web}} does not support |volume= so the equivalent {{citation |website=...}} must not support |volume=. ]] local citation_no_volume_t = { -- {{citation}} does not render |volume= when these parameters are used 'website', 'mailinglist', 'script-website', } local citation_issue_t = { -- {{citation}} may render |issue= when these parameters are used 'journal', 'magazine', 'newspaper', 'periodical', 'work', 'script-journal', 'script-magazine', 'script-newspaper', 'script-periodical', 'script-work', } --[[ Patterns for finding extra text in |volume=, |issue=, |page=, |pages= ]] local vol_iss_pg_patterns = { good_ppattern = '^P[^%.PpGg]', -- OK to begin with uppercase P: P7 (page 7 of section P), but not p123 (page 123); TODO: this allows 'Pages' which it should not bad_ppatterns = { -- patterns for |page= and |pages= '^[Pp][PpGg]?%.?[ %d]', '^[Pp][Pp]?%.&nbsp;', -- from {{p.}} and {{pp.}} templates '^[Pp]ages?', '^[Pp]gs.?', }, vpatterns = { -- patterns for |volume= '^volumes?', '^vols?[%.:=]?' }, ipatterns = { -- patterns for |issue= '^issues?', '^iss[%.:=]?', '^numbers?', '^nos?%A', -- don't match 'november' or 'nostradamus' '^nr[%.:=]?', '^n[%.:= ]' -- might be a valid issue without separator (space char is sep char here) } } --[[--------------------------< K E Y W O R D S >------------------------------- These tables hold keywords for those parameters that have defined sets of acceptable keywords. ]] --[[-------------------< K E Y W O R D S T A B L E >-------------------------- this is a list of keywords; each key in the list is associated with a table of synonymous keywords possibly from different languages. for I18N: add local-language keywords to value table; do not change the key. For example, adding the German keyword 'ja': ['affirmative'] = {'yes', 'true', 'y', 'ja'}, Because CS1|2 templates from en.wiki articles are often copied to other local wikis, it is recommended that the English keywords remain in these tables. ]] local keywords = { ['amp'] = {'&', 'amp', 'ampersand'}, -- |name-list-style= ['and'] = {'and', 'serial'}, -- |name-list-style= ['affirmative'] = {'yes', 'true', 'y'}, -- |no-tracking=, |no-pp= -- Used by InternetArchiveBot ['afterword'] = {'afterword'}, -- |contribution= ['bot: unknown'] = {'bot: unknown'}, -- |url-status= -- Used by InternetArchiveBot ['cs1'] = {'cs1'}, -- |mode= ['cs2'] = {'cs2'}, -- |mode= ['dead'] = {'dead', 'deviated'}, -- |url-status= -- Used by InternetArchiveBot ['dmy'] = {'dmy'}, -- |df= ['dmy-all'] = {'dmy-all'}, -- |df= ['foreword'] = {'foreword'}, -- |contribution= ['free'] = {'free'}, -- |<id>-access= -- Used by InternetArchiveBot ['harv'] = {'harv'}, -- |ref=; this no longer supported; is_valid_parameter_value() called with <invert> = true ['introduction'] = {'introduction'}, -- |contribution= ['limited'] = {'limited'}, -- |url-access= -- Used by InternetArchiveBot ['live'] = {'live'}, -- |url-status= -- Used by InternetArchiveBot ['mdy'] = {'mdy'}, -- |df= ['mdy-all'] = {'mdy-all'}, -- |df= ['none'] = {'none'}, -- |postscript=, |ref=, |title=, |type= -- Used by InternetArchiveBot ['off'] = {'off'}, -- |title= (potentially also: |title-link=, |postscript=, |ref=, |type=) ['preface'] = {'preface'}, -- |contribution= ['registration'] = {'registration'}, -- |url-access= -- Used by InternetArchiveBot ['subscription'] = {'subscription'}, -- |url-access= -- Used by InternetArchiveBot ['unfit'] = {'unfit'}, -- |url-status= -- Used by InternetArchiveBot ['usurped'] = {'usurped'}, -- |url-status= -- Used by InternetArchiveBot ['vanc'] = {'vanc'}, -- |name-list-style= ['ymd'] = {'ymd'}, -- |df= ['ymd-all'] = {'ymd-all'}, -- |df= -- ['yMd'] = {'yMd'}, -- |df=; not supported at en.wiki -- ['yMd-all'] = {'yMd-all'}, -- |df=; not supported at en.wiki } --[[------------------------< X L A T E _ K E Y W O R D S >--------------------- this function builds a list, keywords_xlate{}, of the keywords found in keywords{} where the values from keywords{} become the keys in keywords_xlate{} and the keys from keywords{} become the values in keywords_xlate{}: ['affirmative'] = {'yes', 'true', 'y'}, -- in keywords{} becomes ['yes'] = 'affirmative', -- in keywords_xlate{} ['true'] = 'affirmative', ['y'] = 'affirmative', the purpose of this function is to act as a translator between a non-English keyword and its English equivalent that may be used in other modules of this suite ]] local function xlate_keywords () local out_table = {}; -- output goes here for k, keywords_t in pairs (keywords) do -- spin through the keywords table for _, keyword in ipairs (keywords_t) do -- for each keyword out_table[keyword] = k; -- create an entry in the output table where keyword is the key end end return out_table; end local keywords_xlate = xlate_keywords (); -- the list of translated keywords --[[----------------< M A K E _ K E Y W O R D S _ L I S T >--------------------- this function assembles, for parameter-value validation, the list of keywords appropriate to that parameter. keywords_lists{}, is a table of tables from keywords{} ]] local function make_keywords_list (keywords_lists) local out_table = {}; -- output goes here for _, keyword_list in ipairs (keywords_lists) do -- spin through keywords_lists{} and get a table of keywords for _, keyword in ipairs (keyword_list) do -- spin through keyword_list{} and add each keyword, ... table.insert (out_table, keyword); -- ... as plain text, to the output list end end return out_table; end --[[----------------< K E Y W O R D S _ L I S T S >----------------------------- this is a list of lists of valid keywords for the various parameters in [key]. Generally the keys in this table are the canonical en.wiki parameter names though some are contrived because of use in multiple differently named parameters: ['yes_true_y'], ['id-access']. The function make_keywords_list() extracts the individual keywords from the appropriate list in keywords{}. The lists in this table are used to validate the keyword assignment for the parameters named in this table's keys. ]] local keywords_lists = { ['yes_true_y'] = make_keywords_list ({keywords.affirmative}), ['contribution'] = make_keywords_list ({keywords.afterword, keywords.foreword, keywords.introduction, keywords.preface}), ['df'] = make_keywords_list ({keywords.dmy, keywords['dmy-all'], keywords.mdy, keywords['mdy-all'], keywords.ymd, keywords['ymd-all']}), -- ['df'] = make_keywords_list ({keywords.dmy, keywords['dmy-all'], keywords.mdy, keywords['mdy-all'], keywords.ymd, keywords['ymd-all'], keywords.yMd, keywords['yMd-all']}), -- not supported at en.wiki ['mode'] = make_keywords_list ({keywords.cs1, keywords.cs2}), ['name-list-style'] = make_keywords_list ({keywords.amp, keywords['and'], keywords.vanc}), ['ref'] = make_keywords_list ({keywords.harv}), -- inverted check; |ref=harv no longer supported ['url-access'] = make_keywords_list ({keywords.subscription, keywords.limited, keywords.registration}), ['url-status'] = make_keywords_list ({keywords.dead, keywords.live, keywords.unfit, keywords.usurped, keywords['bot: unknown']}), ['id-access'] = make_keywords_list ({keywords.free}), } --[[---------------------< S T R I P M A R K E R S >---------------------------- Common pattern definition location for stripmarkers so that we don't have to go hunting for them if (when) MediaWiki changes their form. ]] local stripmarkers = { ['any'] = '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', -- capture returns name of stripmarker ['math'] = '\127[^\127]*UNIQ%-%-math%-[%a%d]+%-QINU[^\127]*\127' -- math stripmarkers used in coins_cleanup() and coins_replace_math_stripmarker() } --[[------------< I N V I S I B L E _ C H A R A C T E R S >--------------------- This table holds non-printing or invisible characters indexed either by name or by Unicode group. Values are decimal representations of UTF-8 codes. The table is organized as a table of tables because the Lua pairs keyword returns table data in an arbitrary order. Here, we want to process the table from top to bottom because the entries at the top of the table are also found in the ranges specified by the entries at the bottom of the table. Also here is a pattern that recognizes stripmarkers that begin and end with the delete characters. The nowiki stripmarker is not an error but some others are because the parameter values that include them become part of the template's metadata before stripmarker replacement. ]] local invisible_defs = { del = '\127', -- used to distinguish between stripmarker and del char zwj = '\226\128\141', -- used with capture because zwj may be allowed } local invisible_chars = { {'replacement', '\239\191\189'}, -- U+FFFD, EF BF BD {'zero width joiner', '('.. invisible_defs.zwj .. ')'}, -- U+200D, E2 80 8D; capture because zwj may be allowed {'zero width space', '\226\128\139'}, -- U+200B, E2 80 8B {'hair space', '\226\128\138'}, -- U+200A, E2 80 8A {'soft hyphen', '\194\173'}, -- U+00AD, C2 AD {'horizontal tab', '\009'}, -- U+0009 (HT), 09 {'line feed', '\010'}, -- U+000A (LF), 0A {'no-break space', '\194\160'}, -- U+00A0 (NBSP), C2 A0 {'carriage return', '\013'}, -- U+000D (CR), 0D {'stripmarker', stripmarkers.any}, -- stripmarker; may or may not be an error; capture returns the stripmaker type {'delete', '('.. invisible_defs.del .. ')'}, -- U+007F (DEL), 7F; must be done after stripmarker test; capture to distinguish isolated del chars not part of stripmarker {'C0 control', '[\000-\008\011\012\014-\031]'}, -- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D)) {'C1 control', '[\194\128-\194\159]'}, -- U+0080–U+009F (XXX–APC), C2 80 – C2 9F -- {'Specials', '[\239\191\185-\239\191\191]'}, -- U+FFF9-U+FFFF, EF BF B9 – EF BF BF -- {'Private use area', '[\238\128\128-\239\163\191]'}, -- U+E000–U+F8FF, EE 80 80 – EF A3 BF -- {'Supplementary Private Use Area-A', '[\243\176\128\128-\243\191\191\189]'}, -- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD -- {'Supplementary Private Use Area-B', '[\244\128\128\128-\244\143\191\189]'}, -- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD } --[[ Indic script makes use of zero width joiner as a character modifier so zwj characters must be left in. This pattern covers all of the unicode characters for these languages: Devanagari 0900–097F – https://unicode.org/charts/PDF/U0900.pdf Devanagari extended A8E0–A8FF – https://unicode.org/charts/PDF/UA8E0.pdf Bengali 0980–09FF – https://unicode.org/charts/PDF/U0980.pdf Gurmukhi 0A00–0A7F – https://unicode.org/charts/PDF/U0A00.pdf Gujarati 0A80–0AFF – https://unicode.org/charts/PDF/U0A80.pdf Oriya 0B00–0B7F – https://unicode.org/charts/PDF/U0B00.pdf Tamil 0B80–0BFF – https://unicode.org/charts/PDF/U0B80.pdf Telugu 0C00–0C7F – https://unicode.org/charts/PDF/U0C00.pdf Kannada 0C80–0CFF – https://unicode.org/charts/PDF/U0C80.pdf Malayalam 0D00–0D7F – https://unicode.org/charts/PDF/U0D00.pdf plus the not-necessarily Indic scripts for Sinhala and Burmese: Sinhala 0D80-0DFF - https://unicode.org/charts/PDF/U0D80.pdf Myanmar 1000-109F - https://unicode.org/charts/PDF/U1000.pdf Myanmar extended A AA60-AA7F - https://unicode.org/charts/PDF/UAA60.pdf Myanmar extended B A9E0-A9FF - https://unicode.org/charts/PDF/UA9E0.pdf the pattern is used by has_invisible_chars() and coins_cleanup() ]] local indic_script = '[\224\164\128-\224\181\191\224\163\160-\224\183\191\225\128\128-\225\130\159\234\167\160-\234\167\191\234\169\160-\234\169\191]'; -- list of emoji that use zwj character (U+200D) to combine with another emoji local emoji = { -- indexes are decimal forms of the hex values in U+xxxx [127752] = true, -- U+1F308 🌈 rainbow [127806] = true, -- U+1F33E 🌾 ear of rice [127859] = true, -- U+1F373 🍳 cooking [127891] = true, -- U+1F393 🎓 graduation cap [127908] = true, -- U+1F3A4 🎤 microphone [127912] = true, -- U+1F3A8 🎨 artist palette [127979] = true, -- U+1F3EB 🏫 school [127981] = true, -- U+1F3ED 🏭 factory [128102] = true, -- U+1F466 👦 boy [128103] = true, -- U+1F467 👧 girl [128104] = true, -- U+1F468 👨 man [128105] = true, -- U+1F469 👩 woman [128139] = true, -- U+1F48B 💋 kiss mark [128187] = true, -- U+1F4BB 💻 personal computer [128188] = true, -- U+1F4BC 💼 brief case [128295] = true, -- U+1F527 🔧 wrench [128300] = true, -- U+1F52C 🔬 microscope [128488] = true, -- U+1F5E8 🗨 left speech bubble [128640] = true, -- U+1F680 🚀 rocket [128658] = true, -- U+1F692 🚒 fire engine [129309] = true, -- U+1F91D 🤝 handshake [129455] = true, -- U+1F9AF 🦯 probing cane [129456] = true, -- U+1F9B0 🦰 emoji component red hair [129457] = true, -- U+1F9B1 🦱 emoji component curly hair [129458] = true, -- U+1F9B2 🦲 emoji component bald [129459] = true, -- U+1F9B3 🦳 emoji component white hair [129466] = true, -- U+1F9BA 🦺 safety vest [129468] = true, -- U+1F9BC 🦼 motorized wheelchair [129469] = true, -- U+1F9BD 🦽 manual wheelchair [129489] = true, -- U+1F9D1 🧑 adult [9760] = true, -- U+2620 ☠ skull and crossbones [9792] = true, -- U+2640 ♀ female sign [9794] = true, -- U+2642 ♂ male sign [9877] = true, -- U+2695 ⚕ staff of aesculapius [9878] = true, -- U+2696 ⚖ scales [9992] = true, -- U+2708 ✈ airplane [10084] = true, -- U+2764 ❤ heavy black heart } --[[----------------------< L A N G U A G E S U P P O R T >------------------- These tables and constants support various language-specific functionality. ]] --local this_wiki_code = mw.getContentLanguage():getCode(); -- get this wiki's language code local this_wiki_code = lang_obj:getCode(); -- get this wiki's language code if string.match (mw.site.server, 'wikidata') then this_wiki_code = mw.getCurrentFrame():preprocess('{{int:lang}}'); -- on Wikidata so use interface language setting instead end local mw_languages_by_tag_t = mw.language.fetchLanguageNames (this_wiki_code, 'all'); -- get a table of language tag/name pairs known to Wikimedia; used for interwiki tests local mw_languages_by_name_t = {}; for k, v in pairs (mw_languages_by_tag_t) do -- build a 'reversed' table name/tag language pairs know to MediaWiki; used for |language= v = mw.ustring.lower (v); -- lowercase for tag fetch; get name's proper case from mw_languages_by_tag_t[<tag>] if mw_languages_by_name_t[v] then -- when name already in the table if 2 == #k or 3 == #k then -- if tag does not have subtags mw_languages_by_name_t[v] = k; -- prefer the shortest tag for this name end else -- here when name not in the table mw_languages_by_name_t[v] = k; -- so add name and matching tag end end local inter_wiki_map = {}; -- map of interwiki prefixes that are language-code prefixes for k, v in pairs (mw.site.interwikiMap ('local')) do -- spin through the base interwiki map (limited to local) if mw_languages_by_tag_t[v["prefix"]] then -- if the prefix matches a known language tag inter_wiki_map[v["prefix"]] = true; -- add it to our local map end end --[[--------------------< S C R I P T _ L A N G _ C O D E S >------------------- This table is used to hold ISO 639-1 two-character and ISO 639-3 three-character language codes that apply only to |script-title= and |script-chapter= ]] local script_lang_codes = { 'ab', 'am', 'ar', 'be', 'bg', 'bn', 'bo', 'bs', 'dv', 'dz', 'el', 'fa', 'gu', 'he', 'hi', 'hy', 'ja', 'ka', 'kk', 'km', 'kn', 'ko', 'ku', 'ky', 'lo', 'mk', 'ml', 'mn', 'mr', 'my', 'ne', 'or', 'ota', 'ps', 'ru', 'sd', 'si', 'sr', 'syc', 'ta', 'te', 'tg', 'th', 'ti', 'ug', 'uk', 'ur', 'uz', 'yi', 'yue', 'zh' }; --[[---------------< L A N G U A G E R E M A P P I N G >---------------------- These tables hold language information that is different (correct) from MediaWiki's definitions For each ['code'] = 'language name' in lang_code_remap{} there must be a matching ['language name'] = {'language name', 'code'} in lang_name_remap{} lang_code_remap{}: key is always lowercase ISO 639-1, -2, -3 language code or a valid lowercase IETF language tag value is properly spelled and capitalized language name associated with key only one language name per key; key/value pair must have matching entry in lang_name_remap{} lang_name_remap{}: key is always lowercase language name value is a table the holds correctly spelled and capitalized language name [1] and associated code [2] (code must match a code key in lang_code_remap{}) may have multiple keys referring to a common preferred name and code; For example: ['kolsch'] and ['kölsch'] both refer to 'Kölsch' and 'ksh' ]] local lang_code_remap = { -- used for |language= and |script-title= / |script-chapter= ['als'] = 'Tosk Albanian', -- MediaWiki returns Alemannisch ['bh'] = 'Bihari', -- MediaWiki uses 'bh' as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org ['bla'] = 'Blackfoot', -- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name ['bn'] = 'Bengali', -- MediaWiki returns Bangla ['ca-valencia'] = 'Valencian', -- IETF variant of Catalan ['ilo'] = 'Ilocano', -- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name ['ksh'] = 'Kölsch', -- MediaWiki: Colognian; use IANA/ISO 639 preferred name ['ksh-x-colog'] = 'Colognian', -- override MediaWiki ksh; no IANA/ISO 639 code for Colognian; IETF private code created at Module:Lang/data ['mis-x-ripuar'] = 'Ripuarian', -- override MediaWiki ksh; no IANA/ISO 639 code for Ripuarian; IETF private code created at Module:Lang/data ['nan-tw'] = 'Taiwanese Hokkien', -- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese and support en.wiki preferred name } local lang_name_remap = { -- used for |language=; names require proper capitalization; tags must be lowercase ['alemannisch'] = {'Swiss German', 'gsw'}, -- not an ISO or IANA language name; MediaWiki uses 'als' as a subdomain name for Alemannic Wikipedia: als.wikipedia.org ['bangla'] = {'Bengali', 'bn'}, -- MediaWiki returns Bangla (the endonym) but we want Bengali (the exonym); here we remap ['bengali'] = {'Bengali', 'bn'}, -- MediaWiki doesn't use exonym so here we provide correct language name and 639-1 code ['bhojpuri'] = {'Bhojpuri', 'bho'}, -- MediaWiki uses 'bh' as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org ['bihari'] = {'Bihari', 'bh'}, -- MediaWiki replaces 'Bihari' with 'Bhojpuri' so 'Bihari' cannot be found ['blackfoot'] = {'Blackfoot', 'bla'}, -- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name ['colognian'] = {'Colognian', 'ksh-x-colog'}, -- MediaWiki preferred name for ksh ['ilocano'] = {'Ilocano', 'ilo'}, -- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name ['kolsch'] = {'Kölsch', 'ksh'}, -- use IANA/ISO 639 preferred name (use non-diacritical o instead of umlaut ö) ['kölsch'] = {'Kölsch', 'ksh'}, -- use IANA/ISO 639 preferred name ['ripuarian'] = {'Ripuarian', 'mis-x-ripuar'}, -- group of dialects; no code in MediaWiki or in IANA/ISO 639 ['taiwanese hokkien'] = {'Taiwanese Hokkien', 'nan-tw'}, -- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese ['tosk albanian'] = {'Tosk Albanian', 'als'}, -- MediaWiki replaces 'Tosk Albanian' with 'Alemannisch' so 'Tosk Albanian' cannot be found ['valencian'] = {'Valencian', 'ca'}, -- variant of Catalan; categorizes as Catalan } --[[---------------< P R O P E R T I E S _ C A T E G O R I E S >---------------- Properties categories. These are used for investigating qualities of citations. ]] local prop_cats = { ['foreign-lang-source'] = 'CS1 $1-language sources ($2)', -- |language= categories; $1 is foreign-language name, $2 is ISO639-1 code ['foreign-lang-source-2'] = 'CS1 foreign language sources (ISO 639-2)|$1', -- |language= category; a cat for ISO639-2 languages; $1 is the ISO 639-2 code used as a sort key ['jul-greg-uncertainty'] = 'CS1: Julian–Gregorian uncertainty', -- probably temporary cat to identify scope of template with dates 1 October 1582 – 1 January 1926 ['local-lang-source'] = 'CS1 $1-language sources ($2)', -- |language= categories; $1 is local-language name, $2 is ISO639-1 code; not emitted when local_lang_cat_enable is false ['location-test'] = 'CS1 location test', ['long-vol'] = 'CS1: long volume value', -- probably temporary cat to identify scope of |volume= values longer than 4 charachters ['script'] = 'CS1 uses $1-language script ($2)', -- |script-title=xx: has matching category; $1 is language name, $2 is ISO639-1 code ['tracked-param'] = 'CS1 tracked parameter: $1', -- $1 is base (enumerators removed) parameter name ['year-range-abbreviated'] = 'CS1: abbreviated year range', -- probably temporary cat to identify scope of |date=, |year= values using YYYY–YY form } --[[-------------------< T I T L E _ T Y P E S >-------------------------------- Here we map a template's CitationClass to TitleType (default values for |type= parameter) ]] local title_types = { ['AV-media-notes'] = 'Media notes', ['interview'] = 'Interview', ['mailinglist'] = 'Mailing list', ['map'] = 'Map', ['podcast'] = 'Podcast', ['pressrelease'] = 'Press release', ['report'] = 'Report', ['speech'] = 'Speech', ['techreport'] = 'Technical report', ['thesis'] = 'Thesis', } --[[===================<< E R R O R M E S S A G I N G >>====================== ]] --[[----------< E R R O R M E S S A G E S U P P L I M E N T S >------------- I18N for those messages that are supplemented with additional specific text that describes the reason for the error TODO: merge this with special_case_translations{}? ]] local err_msg_supl = { ['char'] = 'invalid character', -- |isbn=, |sbn= ['check'] = 'checksum', -- |isbn=, |sbn= ['flag'] = 'flag', -- |archive-url= ['form'] = 'invalid form', -- |isbn=, |sbn= ['group'] = 'invalid group id', -- |isbn= ['initials'] = 'initials', -- Vancouver ['invalid language code'] = 'invalid language code', -- |script-<param>= ['journal'] = 'journal', -- |bibcode= ['length'] = 'length', -- |isbn=, |bibcode=, |sbn= ['liveweb'] = 'liveweb', -- |archive-url= ['missing comma'] = 'missing comma', -- Vancouver ['missing prefix'] = 'missing prefix', -- |script-<param>= ['missing title part'] = 'missing title part', -- |script-<param>= ['name'] = 'name', -- Vancouver ['non-Latin char'] = 'non-Latin character', -- Vancouver ['path'] = 'path', -- |archive-url= ['prefix'] = 'invalid prefix', -- |isbn= ['punctuation'] = 'punctuation', -- Vancouver ['save'] = 'save command', -- |archive-url= ['suffix'] = 'suffix', -- Vancouver ['timestamp'] = 'timestamp', -- |archive-url= ['unknown language code'] = 'unknown language code', -- |script-<param>= ['value'] = 'value', -- |bibcode= ['year'] = 'year', -- |bibcode= } --[[--------------< E R R O R _ C O N D I T I O N S >--------------------------- Error condition table. This table has two sections: errors at the top, maintenance at the bottom. Maint 'messaging' does not have a 'message' (message=nil) The following contains a list of IDs for various error conditions defined in the code. For each ID, we specify a text message to display, an error category to include, and whether the error message should be wrapped as a hidden comment. Anchor changes require identical changes to matching anchor in Help:CS1 errors TODO: rename error_conditions{} to something more generic; create separate error and maint tables inside that? ]] local error_conditions = { err_accessdate_missing_url = { message = '<code class="cs1-code">&#124;access-date=</code> requires <code class="cs1-code">&#124;url=</code>', anchor = 'accessdate_missing_url', category = 'CS1 errors: access-date without URL', hidden = false }, err_apostrophe_markup = { message = 'Italic or bold markup not allowed in: <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'apostrophe_markup', category = 'CS1 errors: markup', hidden = false }, err_archive_missing_date = { message = '<code class="cs1-code">&#124;archive-url=</code> requires <code class="cs1-code">&#124;archive-date=</code>', anchor = 'archive_missing_date', category = 'CS1 errors: archive-url', hidden = false }, err_archive_missing_url = { message = '<code class="cs1-code">&#124;archive-url=</code> requires <code class="cs1-code">&#124;url=</code>', anchor = 'archive_missing_url', category = 'CS1 errors: archive-url', hidden = false }, err_archive_url = { message = '<code class="cs1-code">&#124;archive-url=</code> is malformed: $1', -- $1 is error message detail anchor = 'archive_url', category = 'CS1 errors: archive-url', hidden = false }, err_arxiv_missing = { message = '<code class="cs1-code">&#124;arxiv=</code> required', anchor = 'arxiv_missing', category = 'CS1 errors: arXiv', -- same as bad arxiv hidden = false }, err_asintld_missing_asin = { message = '<code class="cs1-code">&#124;$1=</code> requires <code class="cs1-code">&#124;asin=</code>', -- $1 is parameter name anchor = 'asintld_missing_asin', category = 'CS1 errors: ASIN TLD', hidden = false }, err_bad_arxiv = { message = 'Check <code class="cs1-code">&#124;arxiv=</code> value', anchor = 'bad_arxiv', category = 'CS1 errors: arXiv', hidden = false }, err_bad_asin = { message = 'Check <code class="cs1-code">&#124;asin=</code> value', anchor = 'bad_asin', category ='CS1 errors: ASIN', hidden = false }, err_bad_asin_tld = { message = 'Check <code class="cs1-code">&#124;asin-tld=</code> value', anchor = 'bad_asin_tld', category ='CS1 errors: ASIN TLD', hidden = false }, err_bad_bibcode = { message = 'Check <code class="cs1-code">&#124;bibcode=</code> $1', -- $1 is error message detail anchor = 'bad_bibcode', category = 'CS1 errors: bibcode', hidden = false }, err_bad_biorxiv = { message = 'Check <code class="cs1-code">&#124;biorxiv=</code> value', anchor = 'bad_biorxiv', category = 'CS1 errors: bioRxiv', hidden = false }, err_bad_citeseerx = { message = 'Check <code class="cs1-code">&#124;citeseerx=</code> value', anchor = 'bad_citeseerx', category = 'CS1 errors: citeseerx', hidden = false }, err_bad_date = { message = 'Check date values in: $1', -- $1 is a parameter name list anchor = 'bad_date', category = 'CS1 errors: dates', hidden = false }, err_bad_doi = { message = 'Check <code class="cs1-code">&#124;doi=</code> value', anchor = 'bad_doi', category = 'CS1 errors: DOI', hidden = false }, err_bad_hdl = { message = 'Check <code class="cs1-code">&#124;hdl=</code> value', anchor = 'bad_hdl', category = 'CS1 errors: HDL', hidden = false }, err_bad_isbn = { message = 'Check <code class="cs1-code">&#124;isbn=</code> value: $1', -- $1 is error message detail anchor = 'bad_isbn', category = 'CS1 errors: ISBN', hidden = false }, err_bad_ismn = { message = 'Check <code class="cs1-code">&#124;ismn=</code> value', anchor = 'bad_ismn', category = 'CS1 errors: ISMN', hidden = false }, err_bad_issn = { message = 'Check <code class="cs1-code">&#124;$1issn=</code> value', -- $1 is 'e' or '' for eissn or issn anchor = 'bad_issn', category = 'CS1 errors: ISSN', hidden = false }, err_bad_jfm = { message = 'Check <code class="cs1-code">&#124;jfm=</code> value', anchor = 'bad_jfm', category = 'CS1 errors: JFM', hidden = false }, err_bad_jstor = { message = 'Check <code class="cs1-code">&#124;jstor=</code> value', anchor = 'bad_jstor', category = 'CS1 errors: JSTOR', hidden = false }, err_bad_lccn = { message = 'Check <code class="cs1-code">&#124;lccn=</code> value', anchor = 'bad_lccn', category = 'CS1 errors: LCCN', hidden = false }, err_bad_mr = { message = 'Check <code class="cs1-code">&#124;mr=</code> value', anchor = 'bad_mr', category = 'CS1 errors: MR', hidden = false }, err_bad_oclc = { message = 'Check <code class="cs1-code">&#124;oclc=</code> value', anchor = 'bad_oclc', category = 'CS1 errors: OCLC', hidden = false }, err_bad_ol = { message = 'Check <code class="cs1-code">&#124;ol=</code> value', anchor = 'bad_ol', category = 'CS1 errors: OL', hidden = false }, err_bad_osti = { message = 'Check <code class="cs1-code">&#124;osti=</code> value', anchor = 'bad_osti', category = 'CS1 errors: OSTI', hidden = false }, err_bad_paramlink = { -- for |title-link=, |author/editor/translator-link=, |series-link=, |episode-link= message = 'Check <code class="cs1-code">&#124;$1=</code> value', -- $1 is parameter name anchor = 'bad_paramlink', category = 'CS1 errors: parameter link', hidden = false }, err_bad_pmc = { message = 'Check <code class="cs1-code">&#124;pmc=</code> value', anchor = 'bad_pmc', category = 'CS1 errors: PMC', hidden = false }, err_bad_pmid = { message = 'Check <code class="cs1-code">&#124;pmid=</code> value', anchor = 'bad_pmid', category = 'CS1 errors: PMID', hidden = false }, err_bad_rfc = { message = 'Check <code class="cs1-code">&#124;rfc=</code> value', anchor = 'bad_rfc', category = 'CS1 errors: RFC', hidden = false }, err_bad_s2cid = { message = 'Check <code class="cs1-code">&#124;s2cid=</code> value', anchor = 'bad_s2cid', category = 'CS1 errors: S2CID', hidden = false }, err_bad_sbn = { message = 'Check <code class="cs1-code">&#124;sbn=</code> value: $1', -- $1 is error message detail anchor = 'bad_sbn', category = 'CS1 errors: SBN', hidden = false }, err_bad_ssrn = { message = 'Check <code class="cs1-code">&#124;ssrn=</code> value', anchor = 'bad_ssrn', category = 'CS1 errors: SSRN', hidden = false }, err_bad_url = { message = 'Check $1 value', -- $1 is parameter name anchor = 'bad_url', category = 'CS1 errors: URL', hidden = false }, err_bad_usenet_id = { message = 'Check <code class="cs1-code">&#124;message-id=</code> value', anchor = 'bad_message_id', category = 'CS1 errors: message-id', hidden = false }, err_bad_zbl = { message = 'Check <code class="cs1-code">&#124;zbl=</code> value', anchor = 'bad_zbl', category = 'CS1 errors: Zbl', hidden = false }, err_bare_url_missing_title = { message = '$1 missing title', -- $1 is parameter name anchor = 'bare_url_missing_title', category = 'CS1 errors: bare URL', hidden = false }, err_biorxiv_missing = { message = '<code class="cs1-code">&#124;biorxiv=</code> required', anchor = 'biorxiv_missing', category = 'CS1 errors: bioRxiv', -- same as bad bioRxiv hidden = false }, err_chapter_ignored = { message = '<code class="cs1-code">&#124;$1=</code> ignored', -- $1 is parameter name anchor = 'chapter_ignored', category = 'CS1 errors: chapter ignored', hidden = false }, err_citation_missing_title = { message = 'Missing or empty <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'citation_missing_title', category = 'CS1 errors: missing title', hidden = false }, err_citeseerx_missing = { message = '<code class="cs1-code">&#124;citeseerx=</code> required', anchor = 'citeseerx_missing', category = 'CS1 errors: citeseerx', -- same as bad citeseerx hidden = false }, err_cite_web_url = { -- this error applies to cite web and to cite podcast message = 'Missing or empty <code class="cs1-code">&#124;url=</code>', anchor = 'cite_web_url', category = 'CS1 errors: requires URL', hidden = false }, err_class_ignored = { message = '<code class="cs1-code">&#124;class=</code> ignored', anchor = 'class_ignored', category = 'CS1 errors: class', hidden = false }, err_contributor_ignored = { message = '<code class="cs1-code">&#124;contributor=</code> ignored', anchor = 'contributor_ignored', category = 'CS1 errors: contributor', hidden = false }, err_contributor_missing_required_param = { message = '<code class="cs1-code">&#124;contributor=</code> requires <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'contributor_missing_required_param', category = 'CS1 errors: contributor', hidden = false }, err_deprecated_params = { message = 'Cite uses deprecated parameter <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'deprecated_params', category = 'CS1 errors: deprecated parameters', hidden = false }, err_disp_name = { message = 'Invalid <code class="cs1-code">&#124;$1=$2</code>', -- $1 is parameter name; $2 is the assigned value anchor = 'disp_name', category = 'CS1 errors: display-names', hidden = false, }, err_doibroken_missing_doi = { message = '<code class="cs1-code">&#124;$1=</code> requires <code class="cs1-code">&#124;doi=</code>', -- $1 is parameter name anchor = 'doibroken_missing_doi', category = 'CS1 errors: DOI', hidden = false }, err_embargo_missing_pmc = { message = '<code class="cs1-code">&#124;$1=</code> requires <code class="cs1-code">&#124;pmc=</code>', -- $1 is parameter name anchor = 'embargo_missing_pmc', category = 'CS1 errors: PMC embargo', hidden = false }, err_empty_citation = { message = 'Empty citation', anchor = 'empty_citation', category = 'CS1 errors: empty citation', hidden = false }, err_etal = { message = 'Explicit use of et al. in: <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'explicit_et_al', category = 'CS1 errors: explicit use of et al.', hidden = false }, err_extra_text_edition = { message = '<code class="cs1-code">&#124;edition=</code> has extra text', anchor = 'extra_text_edition', category = 'CS1 errors: extra text: edition', hidden = false, }, err_extra_text_issue = { message = '<code class="cs1-code">&#124;$1=</code> has extra text', -- $1 is parameter name anchor = 'extra_text_issue', category = 'CS1 errors: extra text: issue', hidden = false, }, err_extra_text_pages = { message = '<code class="cs1-code">&#124;$1=</code> has extra text', -- $1 is parameter name anchor = 'extra_text_pages', category = 'CS1 errors: extra text: pages', hidden = false, }, err_extra_text_volume = { message = '<code class="cs1-code">&#124;$1=</code> has extra text', -- $1 is parameter name anchor = 'extra_text_volume', category = 'CS1 errors: extra text: volume', hidden = true, }, err_first_missing_last = { message = '<code class="cs1-code">&#124;$1=</code> missing <code class="cs1-code">&#124;$2=</code>', -- $1 is first alias, $2 is matching last alias anchor = 'first_missing_last', category = 'CS1 errors: missing name', -- author, contributor, editor, interviewer, translator hidden = false }, err_format_missing_url = { message = '<code class="cs1-code">&#124;$1=</code> requires <code class="cs1-code">&#124;$2=</code>', -- $1 is format parameter $2 is url parameter anchor = 'format_missing_url', category = 'CS1 errors: format without URL', hidden = false }, err_generic_name = { message = '<code class="cs1-code">&#124;$1=</code> has generic name', -- $1 is parameter name anchor = 'generic_name', category = 'CS1 errors: generic name', hidden = false, }, err_generic_title = { message = 'Cite uses generic title', anchor = 'generic_title', category = 'CS1 errors: generic title', hidden = false, }, err_invalid_param_val = { message = 'Invalid <code class="cs1-code">&#124;$1=$2</code>', -- $1 is parameter name $2 is parameter value anchor = 'invalid_param_val', category = 'CS1 errors: invalid parameter value', hidden = false }, err_invisible_char = { message = '$1 in $2 at position $3', -- $1 is invisible char $2 is parameter name $3 is position number anchor = 'invisible_char', category = 'CS1 errors: invisible characters', hidden = false }, err_missing_name = { message = 'Missing <code class="cs1-code">&#124;$1$2=</code>', -- $1 is modified NameList; $2 is enumerator anchor = 'missing_name', category = 'CS1 errors: missing name', -- author, contributor, editor, interviewer, translator hidden = false }, err_missing_periodical = { message = 'Cite $1 requires <code class="cs1-code">&#124;$2=</code>', -- $1 is cs1 template name; $2 is canonical periodical parameter name for cite $1 anchor = 'missing_periodical', category = 'CS1 errors: missing periodical', hidden = true }, err_missing_pipe = { message = 'Missing pipe in: <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'missing_pipe', category = 'CS1 errors: missing pipe', hidden = false }, err_param_access_requires_param = { message = '<code class="cs1-code">&#124;$1-access=</code> requires <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'param_access_requires_param', category = 'CS1 errors: param-access', hidden = false }, err_param_has_ext_link = { message = 'External link in <code class="cs1-code">$1</code>', -- $1 is parameter name anchor = 'param_has_ext_link', category = 'CS1 errors: external links', hidden = false }, err_parameter_ignored = { message = 'Unknown parameter <code class="cs1-code">&#124;$1=</code> ignored', -- $1 is parameter name anchor = 'parameter_ignored', category = 'CS1 errors: unsupported parameter', hidden = false }, err_parameter_ignored_suggest = { message = 'Unknown parameter <code class="cs1-code">&#124;$1=</code> ignored (<code class="cs1-code">&#124;$2=</code> suggested)', -- $1 is unknown parameter $2 is suggested parameter name anchor = 'parameter_ignored_suggest', category = 'CS1 errors: unsupported parameter', hidden = false }, err_redundant_parameters = { message = 'More than one of $1 specified', -- $1 is error message detail anchor = 'redundant_parameters', category = 'CS1 errors: redundant parameter', hidden = false }, err_script_parameter = { message = 'Invalid <code class="cs1-code">&#124;$1=</code>: $2', -- $1 is parameter name $2 is script language code or error detail anchor = 'script_parameter', category = 'CS1 errors: script parameters', hidden = false }, err_ssrn_missing = { message = '<code class="cs1-code">&#124;ssrn=</code> required', anchor = 'ssrn_missing', category = 'CS1 errors: SSRN', -- same as bad arxiv hidden = false }, err_text_ignored = { message = 'Text "$1" ignored', -- $1 is ignored text anchor = 'text_ignored', category = 'CS1 errors: unrecognized parameter', hidden = false }, err_trans_missing_title = { message = '<code class="cs1-code">&#124;trans-$1=</code> requires <code class="cs1-code">&#124;$1=</code> or <code class="cs1-code">&#124;script-$1=</code>', -- $1 is base parameter name anchor = 'trans_missing_title', category = 'CS1 errors: translated title', hidden = false }, err_param_unknown_empty = { message = 'Cite has empty unknown parameter$1: $2', -- $1 is 's' or empty space; $2 is emty unknown param list anchor = 'param_unknown_empty', category = 'CS1 errors: empty unknown parameters', hidden = false }, err_vancouver = { message = 'Vancouver style error: $1 in name $2', -- $1 is error detail, $2 is the nth name anchor = 'vancouver', category = 'CS1 errors: Vancouver style', hidden = false }, err_wikilink_in_url = { message = 'URL–wikilink conflict', -- uses ndash anchor = 'wikilink_in_url', category = 'CS1 errors: URL–wikilink conflict', -- uses ndash hidden = false }, --[[--------------------------< M A I N T >------------------------------------- maint messages do not have a message (message = nil); otherwise the structure is the same as error messages ]] maint_archived_copy = { message = nil, anchor = 'archived_copy', category = 'CS1 maint: archived copy as title', hidden = true, }, maint_authors = { message = nil, anchor = 'authors', category = 'CS1 maint: uses authors parameter', hidden = true, }, maint_bot_unknown = { message = nil, anchor = 'bot:_unknown', category = 'CS1 maint: bot: original URL status unknown', hidden = true, }, maint_date_auto_xlated = { -- date auto-translation not supported by en.wiki message = nil, anchor = 'date_auto_xlated', category = 'CS1 maint: date auto-translated', hidden = true, }, maint_date_format = { message = nil, anchor = 'date_format', category = 'CS1 maint: date format', hidden = true, }, maint_date_year = { message = nil, anchor = 'date_year', category = 'CS1 maint: date and year', hidden = true, }, maint_doi_ignore = { message = nil, anchor = 'doi_ignore', category = 'CS1 maint: ignored DOI errors', hidden = true, }, maint_doi_inactive = { message = nil, anchor = 'doi_inactive', category = 'CS1 maint: DOI inactive', hidden = true, }, maint_doi_inactive_dated = { message = nil, anchor = 'doi_inactive_dated', category = 'CS1 maint: DOI inactive as of $2$3$1', -- $1 is year, $2 is month-name or empty string, $3 is space or empty string hidden = true, }, maint_extra_punct = { message = nil, anchor = 'extra_punct', category = 'CS1 maint: extra punctuation', hidden = true, }, maint_isbn_ignore = { message = nil, anchor = 'ignore_isbn_err', category = 'CS1 maint: ignored ISBN errors', hidden = true, }, maint_issn_ignore = { message = nil, anchor = 'ignore_issn', category = 'CS1 maint: ignored ISSN errors', hidden = true, }, maint_jfm_format = { message = nil, anchor = 'jfm_format', category = 'CS1 maint: JFM format', hidden = true, }, maint_location = { message = nil, anchor = 'location', category = 'CS1 maint: location', hidden = true, }, maint_mr_format = { message = nil, anchor = 'mr_format', category = 'CS1 maint: MR format', hidden = true, }, maint_mult_names = { message = nil, anchor = 'mult_names', category = 'CS1 maint: multiple names: $1', -- $1 is '<name>s list'; gets value from special_case_translation table hidden = true, }, maint_numeric_names = { message = nil, anchor = 'numeric_names', category = 'CS1 maint: numeric names: $1', -- $1 is '<name>s list'; gets value from special_case_translation table hidden = true, }, maint_others = { message = nil, anchor = 'others', category = 'CS1 maint: others', hidden = true, }, maint_others_avm = { message = nil, anchor = 'others_avm', category = 'CS1 maint: others in cite AV media (notes)', hidden = true, }, maint_pmc_embargo = { message = nil, anchor = 'embargo', category = 'CS1 maint: PMC embargo expired', hidden = true, }, maint_pmc_format = { message = nil, anchor = 'pmc_format', category = 'CS1 maint: PMC format', hidden = true, }, maint_postscript = { message = nil, anchor = 'postscript', category = 'CS1 maint: postscript', hidden = true, }, maint_ref_duplicates_default = { message = nil, anchor = 'ref_default', category = 'CS1 maint: ref duplicates default', hidden = true, }, maint_unfit = { message = nil, anchor = 'unfit', category = 'CS1 maint: unfit URL', hidden = true, }, maint_unknown_lang = { message = nil, anchor = 'unknown_lang', category = 'CS1 maint: unrecognized language', hidden = true, }, maint_untitled = { message = nil, anchor = 'untitled', category = 'CS1 maint: untitled periodical', hidden = true, }, maint_url_status = { message = nil, anchor = 'url_status', category = 'CS1 maint: url-status', hidden = true, }, maint_zbl = { message = nil, anchor = 'zbl', category = 'CS1 maint: Zbl', hidden = true, }, } --[[--------------------------< I D _ H A N D L E R S >-------------------------------------------------------- The following contains a list of values for various defined identifiers. For each identifier we specify a variety of information necessary to properly render the identifier in the citation. parameters: a list of parameter aliases for this identifier; first in the list is the canonical form link: Wikipedia article name redirect: a local redirect to a local Wikipedia article name; at en.wiki, 'ISBN (identifier)' is a redirect to 'International Standard Book Number' q: Wikidata q number for the identifier label: the label preceeding the identifier; label is linked to a Wikipedia article (in this order): redirect from id_handlers['<id>'].redirect when use_identifier_redirects is true Wikidata-supplied article name for the local wiki from id_handlers['<id>'].q local article name from id_handlers['<id>'].link prefix: the first part of a URL that will be concatenated with a second part which usually contains the identifier suffix: optional third part to be added after the identifier encode: true if URI should be percent-encoded; otherwise false COinS: identifier link or keyword for use in COinS: for identifiers registered at info-uri.info use: info:.... where '...' is the appropriate identifier label for identifiers that have COinS keywords, use the keyword: rft.isbn, rft.issn, rft.eissn for |asin= and |ol=, which require assembly, use the keyword: url for others make a URL using the value in prefix/suffix and #label, use the keyword: pre (not checked; any text other than 'info', 'rft', or 'url' works here) set to nil to leave the identifier out of the COinS separator: character or text between label and the identifier in the rendered citation id_limit: for those identifiers with established limits, this property holds the upper limit access: use this parameter to set the access level for all instances of this identifier. the value must be a valid access level for an identifier (see ['id-access'] in this file). custom_access: to enable custom access level for an identifier, set this parameter to the parameter that should control it (normally 'id-access') ]] local id_handlers = { ['ARXIV'] = { parameters = {'arxiv', 'eprint'}, link = 'arXiv', redirect = 'arXiv (identifier)', q = 'Q118398', label = 'arXiv', prefix = '//arxiv.org/abs/', -- protocol-relative tested 2013-09-04 encode = false, COinS = 'info:arxiv', separator = ':', access = 'free', -- free to read }, ['ASIN'] = { parameters = { 'asin', 'ASIN' }, link = 'Amazon Standard Identification Number', redirect = 'ASIN (identifier)', q = 'Q1753278', label = 'ASIN', prefix = '//www.amazon.', COinS = 'url', separator = '&nbsp;', encode = false; }, ['BIBCODE'] = { parameters = {'bibcode'}, link = 'Bibcode', redirect = 'Bibcode (identifier)', q = 'Q25754', label = 'Bibcode', prefix = 'https://ui.adsabs.harvard.edu/abs/', encode = false, COinS = 'info:bibcode', separator = ':', custom_access = 'bibcode-access', }, ['BIORXIV'] = { parameters = {'biorxiv'}, link = 'bioRxiv', redirect = 'bioRxiv (identifier)', q = 'Q19835482', label = 'bioRxiv', prefix = '//doi.org/', COinS = 'pre', -- use prefix value access = 'free', -- free to read encode = true, separator = '&nbsp;', }, ['CITESEERX'] = { parameters = {'citeseerx'}, link = 'CiteSeerX', redirect = 'CiteSeerX (identifier)', q = 'Q2715061', label = 'CiteSeerX', prefix = '//citeseerx.ist.psu.edu/viewdoc/summary?doi=', COinS = 'pre', -- use prefix value access = 'free', -- free to read encode = true, separator = '&nbsp;', }, ['DOI'] = { -- Used by InternetArchiveBot parameters = { 'doi', 'DOI'}, link = 'Digital object identifier', redirect = 'doi (identifier)', q = 'Q25670', label = 'doi', prefix = '//doi.org/', COinS = 'info:doi', separator = ':', encode = true, custom_access = 'doi-access', }, ['EISSN'] = { parameters = {'eissn', 'EISSN'}, link = 'International Standard Serial Number#Electronic ISSN', redirect = 'eISSN (identifier)', q = 'Q46339674', label = 'eISSN', prefix = '//www.worldcat.org/issn/', COinS = 'rft.eissn', encode = false, separator = '&nbsp;', }, ['HDL'] = { parameters = { 'hdl', 'HDL' }, link = 'Handle System', redirect = 'hdl (identifier)', q = 'Q3126718', label = 'hdl', prefix = '//hdl.handle.net/', COinS = 'info:hdl', separator = ':', encode = true, custom_access = 'hdl-access', }, ['ISBN'] = { -- Used by InternetArchiveBot parameters = {'isbn', 'ISBN'}, link = 'International Standard Book Number', redirect = 'ISBN (identifier)', q = 'Q33057', label = 'ISBN', prefix = 'Special:BookSources/', COinS = 'rft.isbn', separator = '&nbsp;', }, ['ISMN'] = { parameters = {'ismn', 'ISMN'}, link = 'International Standard Music Number', redirect = 'ISMN (identifier)', q = 'Q1666938', label = 'ISMN', prefix = '', -- not currently used; COinS = nil, -- nil because we can't use pre or rft or info: separator = '&nbsp;', }, ['ISSN'] = { parameters = {'issn', 'ISSN'}, link = 'International Standard Serial Number', redirect = 'ISSN (identifier)', q = 'Q131276', label = 'ISSN', prefix = '//www.worldcat.org/issn/', COinS = 'rft.issn', encode = false, separator = '&nbsp;', }, ['JFM'] = { parameters = {'jfm', 'JFM'}, link = 'Jahrbuch über die Fortschritte der Mathematik', redirect = 'JFM (identifier)', q = '', label = 'JFM', prefix = '//zbmath.org/?format=complete&q=an:', COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', }, ['JSTOR'] = { parameters = {'jstor', 'JSTOR'}, link = 'JSTOR', redirect = 'JSTOR (identifier)', q = 'Q1420342', label = 'JSTOR', prefix = '//www.jstor.org/stable/', -- protocol-relative tested 2013-09-04 COinS = 'pre', -- use prefix value encode = false, separator = '&nbsp;', custom_access = 'jstor-access', }, ['LCCN'] = { parameters = {'lccn', 'LCCN'}, link = 'Library of Congress Control Number', redirect = 'LCCN (identifier)', q = 'Q620946', label = 'LCCN', prefix = '//lccn.loc.gov/', -- protocol-relative tested 2015-12-28 COinS = 'info:lccn', encode = false, separator = '&nbsp;', }, ['MR'] = { parameters = {'mr', 'MR'}, link = 'Mathematical Reviews', redirect = 'MR (identifier)', q = 'Q211172', label = 'MR', prefix = '//www.ams.org/mathscinet-getitem?mr=', -- protocol-relative tested 2013-09-04 COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', }, ['OCLC'] = { parameters = {'oclc', 'OCLC'}, link = 'OCLC', redirect = 'OCLC (identifier)', q = 'Q190593', label = 'OCLC', prefix = '//www.worldcat.org/oclc/', COinS = 'info:oclcnum', encode = true, separator = '&nbsp;', id_limit = 9999999999, -- 10-digits }, ['OL'] = { parameters = { 'ol', 'OL' }, link = 'Open Library', redirect = 'OL (identifier)', q = 'Q1201876', label = 'OL', prefix = '//openlibrary.org/', COinS = 'url', separator = '&nbsp;', encode = true, custom_access = 'ol-access', }, ['OSTI'] = { parameters = {'osti', 'OSTI'}, link = 'Office of Scientific and Technical Information', redirect = 'OSTI (identifier)', q = 'Q2015776', label = 'OSTI', prefix = '//www.osti.gov/biblio/', -- protocol-relative tested 2018-09-12 COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', id_limit = 23010000, custom_access = 'osti-access', }, ['PMC'] = { parameters = {'pmc', 'PMC'}, link = 'PubMed Central', redirect = 'PMC (identifier)', q = 'Q229883', label = 'PMC', prefix = '//www.ncbi.nlm.nih.gov/pmc/articles/PMC', suffix = '', COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', id_limit = 9500000, access = 'free', -- free to read }, ['PMID'] = { parameters = {'pmid', 'PMID'}, link = 'PubMed Identifier', redirect = 'PMID (identifier)', q = 'Q2082879', label = 'PMID', prefix = '//pubmed.ncbi.nlm.nih.gov/', COinS = 'info:pmid', encode = false, separator = '&nbsp;', id_limit = 36400000, }, ['RFC'] = { parameters = {'rfc', 'RFC'}, link = 'Request for Comments', redirect = 'RFC (identifier)', q = 'Q212971', label = 'RFC', prefix = '//tools.ietf.org/html/rfc', COinS = 'pre', -- use prefix value encode = false, separator = '&nbsp;', id_limit = 9300, access = 'free', -- free to read }, ['SBN'] = { parameters = {'sbn', 'SBN'}, link = 'Standard Book Number', -- redirect to International_Standard_Book_Number#History redirect = 'SBN (identifier)', label = 'SBN', prefix = 'Special:BookSources/0-', -- prefix has leading zero necessary to make 9-digit sbn a 10-digit isbn COinS = nil, -- nil because we can't use pre or rft or info: separator = '&nbsp;', }, ['SSRN'] = { parameters = {'ssrn', 'SSRN'}, link = 'Social Science Research Network', redirect = 'SSRN (identifier)', q = 'Q7550801', label = 'SSRN', prefix = '//ssrn.com/abstract=', -- protocol-relative tested 2013-09-04 COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', id_limit = 4200000, custom_access = 'ssrn-access', }, ['S2CID'] = { parameters = {'s2cid', 'S2CID'}, link = 'Semantic Scholar', redirect = 'S2CID (identifier)', q = 'Q22908627', label = 'S2CID', prefix = 'https://api.semanticscholar.org/CorpusID:', COinS = 'pre', -- use prefix value encode = false, separator = '&nbsp;', id_limit = 254000000, custom_access = 's2cid-access', }, ['USENETID'] = { parameters = {'message-id'}, link = 'Usenet', redirect = 'Usenet (identifier)', q = 'Q193162', label = 'Usenet:', prefix = 'news:', encode = false, COinS = 'pre', -- use prefix value separator = '&nbsp;', }, ['ZBL'] = { parameters = {'zbl', 'ZBL' }, link = 'Zentralblatt MATH', redirect = 'Zbl (identifier)', q = 'Q190269', label = 'Zbl', prefix = '//zbmath.org/?format=complete&q=an:', COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', }, } --[[--------------------------< E X P O R T S >--------------------------------- ]] return { use_identifier_redirects = true, -- when true use redirect name for identifier label links; always true at en.wiki local_lang_cat_enable = false; -- when true categorizes pages where |language=<local wiki's language>; always false at en.wiki date_name_auto_xlate_enable = false; -- when true translates English month-names to the local-wiki's language month names; always false at en.wiki date_digit_auto_xlate_enable = false; -- when true translates Western date digit to the local-wiki's language digits (date_names['local_digits']); always false at en.wiki global_df = get_date_format (), -- tables and variables created when this module is loaded punct_skip = build_skip_table (punct_skip, punct_meta_params), url_skip = build_skip_table (url_skip, url_meta_params), aliases = aliases, special_case_translation = special_case_translation, date_names = date_names, err_msg_supl = err_msg_supl, error_conditions = error_conditions, editor_markup_patterns = editor_markup_patterns, et_al_patterns = et_al_patterns, id_handlers = id_handlers, keywords_lists = keywords_lists, keywords_xlate = keywords_xlate, stripmarkers=stripmarkers, invisible_chars = invisible_chars, invisible_defs = invisible_defs, indic_script = indic_script, emoji = emoji, maint_cats = maint_cats, messages = messages, presentation = presentation, prop_cats = prop_cats, script_lang_codes = script_lang_codes, lang_code_remap = lang_code_remap, lang_name_remap = lang_name_remap, this_wiki_code = this_wiki_code, title_types = title_types, uncategorized_namespaces = uncategorized_namespaces, uncategorized_subpages = uncategorized_subpages, templates_using_volume = templates_using_volume, templates_using_issue = templates_using_issue, templates_not_using_page = templates_not_using_page, vol_iss_pg_patterns = vol_iss_pg_patterns, inter_wiki_map = inter_wiki_map, mw_languages_by_tag_t = mw_languages_by_tag_t, mw_languages_by_name_t = mw_languages_by_name_t, citation_class_map_t = citation_class_map_t, citation_issue_t = citation_issue_t, citation_no_volume_t = citation_no_volume_t, } eece11b3085eb39f5bb266336c4c5afa7a6eaa74 Template:Sclass/core 10 129 273 2022-08-04T14:50:18Z Canopus >Dinoguy1000 0 simplify code a bit wikitext text/x-wiki <includeonly>[[{{{1}}}-class {{{2}}} {{#if:{{{5|}}}|({{{5}}})}}|{{#switch:{{{format}}} |sclass =''{{{1}}}'' |sclass2 ={{{1}}} }}<!-- -->{{#switch:{{{3|}}} |=-class]] [[{{#if:{{{4|}}}|{{{2}}} ({{{4}}}){{!}}{{{2}}}|{{{2}}}}}]] |0 =-class]] |1 =-class&#x20;{{{2}}}]] |2 =-class]] {{{2}}} |3 =-class]] [[{{#if:{{{4|}}}|{{{2}}} ({{{4}}}){{!}}{{{2}}}|{{{2}}}}}]] |4 =&#x20;class]] |5 =]] |6|#default=-class&#x20;{{{2}}}]]<!-- same as 1, 3; warning + cat -->{{preview warning|[[Template:{{{format|}}}|Template {{ucfirst:{{{format|}}}}}]], invalid format code: {{{3|}}}. Should be 1&ndash;5, or blank.}}{{main other|[[Category:WPSHIPS: sclass invalid option]]}}<!-- -->}}<!-- eo switch --></includeonly><noinclude>{{documentation}}</noinclude> d536aa9b427477a08e0d51d8dc68ef00c5c82098 Module:Hatnote 828 107 229 2022-08-18T19:31:48Z Canopus >Nihiltres 0 Updated from sandbox: export default classes through new function p.defaultClasses Scribunto text/plain -------------------------------------------------------------------------------- -- Module:Hatnote -- -- -- -- This module produces hatnote links and links to related articles. It -- -- implements the {{hatnote}} and {{format link}} meta-templates and includes -- -- helper functions for other Lua hatnote modules. -- -------------------------------------------------------------------------------- local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg local mArguments -- lazily initialise [[Module:Arguments]] local yesno -- lazily initialise [[Module:Yesno]] local formatLink -- lazily initialise [[Module:Format link]] ._formatLink local p = {} -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- local curNs = mw.title.getCurrentTitle().namespace p.missingTargetCat = --Default missing target category, exported for use in related modules ((curNs == 0) or (curNs == 14)) and 'Articles with hatnote templates targeting a nonexistent page' or nil local function getArgs(frame) -- Fetches the arguments from the parent frame. Whitespace is trimmed and -- blanks are removed. mArguments = require('Module:Arguments') return mArguments.getArgs(frame, {parentOnly = true}) end local function removeInitialColon(s) -- Removes the initial colon from a string, if present. return s:match('^:?(.*)') end function p.findNamespaceId(link, removeColon) -- Finds the namespace id (namespace number) of a link or a pagename. This -- function will not work if the link is enclosed in double brackets. Colons -- are trimmed from the start of the link by default. To skip colon -- trimming, set the removeColon parameter to false. checkType('findNamespaceId', 1, link, 'string') checkType('findNamespaceId', 2, removeColon, 'boolean', true) if removeColon ~= false then link = removeInitialColon(link) end local namespace = link:match('^(.-):') if namespace then local nsTable = mw.site.namespaces[namespace] if nsTable then return nsTable.id end end return 0 end function p.makeWikitextError(msg, helpLink, addTrackingCategory, title) -- Formats an error message to be returned to wikitext. If -- addTrackingCategory is not false after being returned from -- [[Module:Yesno]], and if we are not on a talk page, a tracking category -- is added. checkType('makeWikitextError', 1, msg, 'string') checkType('makeWikitextError', 2, helpLink, 'string', true) yesno = require('Module:Yesno') title = title or mw.title.getCurrentTitle() -- Make the help link text. local helpText if helpLink then helpText = ' ([[' .. helpLink .. '|help]])' else helpText = '' end -- Make the category text. local category if not title.isTalkPage -- Don't categorise talk pages and title.namespace ~= 2 -- Don't categorise userspace and yesno(addTrackingCategory) ~= false -- Allow opting out then category = 'Hatnote templates with errors' category = mw.ustring.format( '[[%s:%s]]', mw.site.namespaces[14].name, category ) else category = '' end return mw.ustring.format( '<strong class="error">Error: %s%s.</strong>%s', msg, helpText, category ) end function p.disambiguate(page, disambiguator) -- Formats a page title with a disambiguation parenthetical, -- i.e. "Example" → "Example (disambiguation)". checkType('disambiguate', 1, page, 'string') checkType('disambiguate', 2, disambiguator, 'string', true) disambiguator = disambiguator or 'disambiguation' return mw.ustring.format('%s (%s)', page, disambiguator) end function p.defaultClasses(inline) -- Provides the default hatnote classes as a space-separated string; useful -- for hatnote-manipulation modules like [[Module:Hatnote group]]. return (inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' .. 'navigation-not-searchable' end -------------------------------------------------------------------------------- -- Hatnote -- -- Produces standard hatnote text. Implements the {{hatnote}} template. -------------------------------------------------------------------------------- function p.hatnote(frame) local args = getArgs(frame) local s = args[1] if not s then return p.makeWikitextError( 'no text specified', 'Template:Hatnote#Errors', args.category ) end return p._hatnote(s, { extraclasses = args.extraclasses, selfref = args.selfref }) end function p._hatnote(s, options) checkType('_hatnote', 1, s, 'string') checkType('_hatnote', 2, options, 'table', true) options = options or {} local inline = options.inline local hatnote = mw.html.create(inline == 1 and 'span' or 'div') local extraclasses if type(options.extraclasses) == 'string' then extraclasses = options.extraclasses end hatnote :attr('role', 'note') :addClass(p.defaultClasses(inline)) :addClass(extraclasses) :addClass(options.selfref and 'selfref' or nil) :wikitext(s) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' } } .. tostring(hatnote) end return p 7a49bd6a35a51b9e77a9c2c6f8f09a4738d7d68e Module:Footnotes/whitelist 828 105 225 2022-08-19T19:09:59Z Canopus >Renata3 0 + batch from Activelydisinterested Scribunto text/plain --[[--------------------------< W R A P P E R _ T E M P L A T E _ D E F A U L T S >---------------------------- A list of wrapper templates by their canonical names – spelling and capitalization is important. Each wrapper template has a table of two values: [1] is the wrapper's default name-list as it is used in an anchor ID; [2] is the default year. This table is indexed indirectly through the wrapper_templates table. This table is not available externally. ]] local wrapper_template_defaults = { -- keys are canonical template names ['Americana'] = {'Rines', '1920'}, -- tables with default name and default year ['Cite EB1911'] = {'Chisholm', '1911'}, -- tables with default name and default year ['EB1911'] = {'Chisholm', '1911'}, ['EI3'] = {'FleetKrämerMatringeNawas', ''}, ['ODNB'] = {'', ''}, -- there is no default anchor ID; this forces evaluation of {{cite ODNB}} redirects } --[[--------------------------< W R A P P E R _ T E M P L A T E _ D E F A U L T S _ V O L >-------------------- For wrapper templates that use |volume= to specify default name (often editor names) and year. Wrapper templates are indexed by their canonical names – spelling and capitalization is important. Each wrapper template has a table of values for every volume. Volumes may be indexed by Arabic or Roman numerals. Each volume index has a table of twp values" [1] is the wrapper's default name-list as it is used in an anchor ID; [2] is the default year. Each wrapper template in this table must have a ['default'] key for those occasions when |volume= is omitted or empty. This table is indexed indirectly through the wrapper_templates table. This table is not available externally. ]] local wrapper_template_defaults_vol = { -- primary keys are canonical template names; TODO: do these keys have to be canonical template names? ['Cite Catholic Encyclopedia'] = { -- secondary keys are volume ['1'] = {'Herbermann', '1907'}, ['2'] = {'Herbermann', '1907'}, ['3'] = {'Herbermann', '1908'}, ['4'] = {'Herbermann', '1908'}, ['5'] = {'Herbermann', '1909'}, ['6'] = {'Herbermann', '1909'}, ['7'] = {'Herbermann', '1910'}, ['8'] = {'Herbermann', '1910'}, ['9'] = {'Herbermann', '1910'}, ['10'] = {'Herbermann', '1911'}, ['11'] = {'Herbermann', '1911'}, ['12'] = {'Herbermann', '1911'}, ['13'] = {'Herbermann', '1912'}, ['14'] = {'Herbermann', '1912'}, ['15'] = {'Herbermann', '1912'}, ['default'] = {'Herbermann', '1913'}, }, ['Cite EB9'] = { ['1'] = {'Baynes', '1878'}, ['I'] = {'Baynes', '1878'}, ['2'] = {'Baynes', '1878'}, ['II'] = {'Baynes', '1878'}, ['3'] = {'Baynes', '1878'}, ['III'] = {'Baynes', '1878'}, ['4'] = {'Baynes', '1878'}, ['IV'] = {'Baynes', '1878'}, ['5'] = {'Baynes', '1878'}, ['V'] = {'Baynes', '1878'}, ['6'] = {'Baynes', '1878'}, ['VI'] = {'Baynes', '1878'}, ['7'] = {'Baynes', '1878'}, ['VII'] = {'Baynes', '1878'}, ['8'] = {'Baynes', '1878'}, ['VIII'] = {'Baynes', '1878'}, ['9'] = {'Baynes', '1879'}, ['IX'] = {'Baynes', '1879'}, ['10'] = {'Baynes', '1879'}, ['X'] = {'Baynes', '1879'}, ['11'] = {'BaynesSmith', '1880'}, ['XI'] = {'BaynesSmith', '1880'}, ['12'] = {'BaynesSmith', '1881'}, ['XII'] = {'BaynesSmith', '1881'}, ['13'] = {'BaynesSmith', '1881'}, ['XIII'] = {'BaynesSmith', '1881'}, ['14'] = {'BaynesSmith', '1882'}, ['XIV'] = {'BaynesSmith', '1882'}, ['15'] = {'BaynesSmith', '1883'}, ['XV'] = {'BaynesSmith', '1883'}, ['16'] = {'BaynesSmith', '1883'}, ['XVI'] = {'BaynesSmith', '1883'}, ['17'] = {'BaynesSmith', '1884'}, ['XVII'] = {'BaynesSmith', '1884'}, ['18'] = {'BaynesSmith', '1885'}, ['XVIII'] = {'BaynesSmith', '1885'}, ['19'] = {'BaynesSmith', '1885'}, ['XIX'] = {'BaynesSmith', '1885'}, ['20'] = {'BaynesSmith', '1886'}, ['XX'] = {'BaynesSmith', '1886'}, ['21'] = {'BaynesSmith', '1886'}, ['XXI'] = {'BaynesSmith', '1886'}, ['22'] = {'BaynesSmith', '1887'}, ['XXII'] = {'BaynesSmith', '1887'}, ['23'] = {'BaynesSmith', '1888'}, ['XXIII'] = {'BaynesSmith', '1888'}, ['24'] = {'BaynesSmith', '1888'}, ['XXIV'] = {'BaynesSmith', '1888'}, ['default'] = {'Baynes', '1875–1889'}, }, ['Encyclopaedia of Islam, New Edition'] = { ['1'] = {'GibbKramersLévi-ProvençalSchacht', '1960'}, ['2'] = {'LewisPellatSchacht', '1965'}, ['3'] = {'LewisMénagePellatSchacht', '1971'}, ['4'] = {'van_DonzelLewisPellatBosworth', '1978'}, ['5'] = {'Bosworthvan_DonzelLewisPellat', '1986'}, ['6'] = {'Bosworthvan_DonzelPellat', '1991'}, ['7'] = {'Bosworthvan_DonzelHeinrichsPellat', '1993'}, ['8'] = {'Bosworthvan_DonzelHeinrichsLecomte', '1995'}, ['9'] = {'Bosworthvan_DonzelHeinrichsLecomte', '1997'}, ['10'] = {'BearmanBianquisBosworthvan_Donzel', '2000'}, ['11'] = {'BearmanBianquisBosworthvan_Donzel', '2002'}, ['12'] = {'BearmanBianquisBosworthvan_Donzel', '2004'}, ['atlas'] = {'Brice', '1981'}, ['abridged'] = {'van_Donzel', '1994'}, ['default'] = {'BearmanBianquisBosworthvan_Donzel', '1960–2005'}, }, ['New Cambridge Medieval History'] = { ['1'] = {'Fouracre', '2005'}, ['2'] = {'McKitterick', '1995'}, ['3'] = {'Reuter', '2000'}, ['4a'] = {'LuscombeRiley-Smith', '2004'}, ['4b'] = {'LuscombeRiley-Smith', '2004'}, ['5'] = {'Abulafia', '1999'}, ['6'] = {'Jones', '2000'}, ['7'] = {'Allmand', '1998'}, ['default'] = {'', '1995–2005'}, }, ['The History of al-Tabari'] = { ['1'] = {'Rosenthal', '1989'}, ['2'] = {'Brinner', '1986'}, ['3'] = {'Brinner', '1991'}, ['4'] = {'Perlmann', '1987'}, ['5'] = {'Bosworth', '1999'}, ['6'] = {'WattMcDonald', '1989'}, ['7'] = {'McDonald', '1987'}, ['8'] = {'Fishbein', '1997'}, ['9'] = {'Poonawala', '1990'}, ['10'] = {'Donner', '1993'}, ['11'] = {'Blankinship', '1993'}, ['12'] = {'Friedmann', '1992'}, ['13'] = {'Juynboll', '1989'}, ['14'] = {'Smith', '1994'}, ['15'] = {'Humphreys', '1990'}, ['16'] = {'Brockett', '1997'}, ['17'] = {'Hawting', '1996'}, ['18'] = {'Morony', '1987'}, ['19'] = {'Howard', '1990'}, ['20'] = {'Hawting', '1989'}, ['21'] = {'Fishbein', '1990'}, ['22'] = {'Rowson', '1989'}, ['23'] = {'Hinds', '1990'}, ['24'] = {'Powers', '1989'}, ['25'] = {'Blankinship', '1989'}, ['26'] = {'Hillenbrand', '1989'}, ['27'] = {'Williams', '1985'}, ['28'] = {'McAuliffe', '1995'}, ['29'] = {'Kennedy', '1990'}, ['30'] = {'Bosworth', '1989'}, ['31'] = {'Fishbein', '1992'}, ['32'] = {'Bosworth', '1987'}, ['33'] = {'Bosworth', '1991'}, ['34'] = {'Kraemer', '1989'}, ['35'] = {'Saliba', '1985'}, ['36'] = {'Waines', '1992'}, ['37'] = {'Fields', '1987'}, ['38'] = {'Rosenthal', '1985'}, ['39'] = {'Landau-Tasseron', '1998'}, ['40'] = {'Popovkin', '2007'}, ['default'] = {'Yarshater', '1985–2007'}, }, } --[[--------------------------< W R A P P E R _ T E M P L A T E S >-------------------------------------------- A list of wrapper templates and their redirects – spelling and capitalization is important; first character is always uppercase. Each wrapper template gets its value from a k/v pair in the wrapper_template_defaults table. article reader queries this table to see if template_name is a wrapper template ]] local wrapper_templates = { -- keys are names of wrapper templates and their redirects ['Americana'] = wrapper_template_defaults['Americana'], -- canonical name; this template calls Cite Americana ['Catholic Encyclopedia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['1913Catholic'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Catholic'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Catholic encyclopedia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['CatholicEncyclopedia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['CE13'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['CE1913'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Cite Americana'] = wrapper_template_defaults['Americana'], -- canonical name ['Cite Catholic Encyclopedia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['CathEncy'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Cite Catholic Encyclopædia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Cite CE1913'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Cite EB1911'] = wrapper_template_defaults['Cite EB1911'], -- canonical name ['1911EB'] = wrapper_template_defaults['Cite EB1911'], -- redirects ['EB1911 cite'] = wrapper_template_defaults['Cite EB1911'], ['Wikisource1911Enc Citation'] = wrapper_template_defaults['Cite EB1911'], ['Wikisource1911Enc citation'] = wrapper_template_defaults['Cite EB1911'], ['Cite EB9'] = wrapper_template_defaults_vol['Cite EB9'], -- canonical ['Eb9'] = wrapper_template_defaults_vol['Cite EB9'], ['Cite ODNB'] = wrapper_template_defaults['ODNB'], -- canonical ['Cite odnb'] = wrapper_template_defaults['ODNB'], ['DNBweb'] = wrapper_template_defaults['ODNB'], ['OBDNweb'] = wrapper_template_defaults['ODNB'], ['ODNB'] = wrapper_template_defaults['ODNB'], ['ODNBref'] = wrapper_template_defaults['ODNB'], ['ODNBweb'] = wrapper_template_defaults['ODNB'], ['EB1911'] = wrapper_template_defaults['EB1911'], -- canonical name; this template calls Cite EB1911 ['1911'] = wrapper_template_defaults['EB1911'], -- redirects ['1911s'] = wrapper_template_defaults['EB1911'], ['Britannica 1911'] = wrapper_template_defaults['EB1911'], ['Encyclopedia Britannica 1911'] = wrapper_template_defaults['EB1911'], ['Encyclopædia Britannica 1911'] = wrapper_template_defaults['EB1911'], ['EB9'] = wrapper_template_defaults_vol['Cite EB9'], -- canonical; this template calls Cite EB9 ['Encyclopaedia of Islam, New Edition'] = wrapper_template_defaults_vol['Encyclopaedia of Islam, New Edition'], -- canonical ['EI2'] = wrapper_template_defaults_vol['Encyclopaedia of Islam, New Edition'], ['Encyclopaedia of Islam, THREE'] = wrapper_template_defaults['EI3'], -- canonical ['EI3'] = wrapper_template_defaults['EI3'], ['New Cambridge Medieval History'] = wrapper_template_defaults_vol['New Cambridge Medieval History'], -- canonical ['The History of al-Tabari'] = wrapper_template_defaults_vol['The History of al-Tabari'], -- canonical ['The History of Al-Tabari'] = wrapper_template_defaults_vol['The History of al-Tabari'], -- redirects ['The History of al-Ṭabarī'] = wrapper_template_defaults_vol['The History of al-Tabari'], -- redirects } --[[--------------------------< T E M P L A T E _ N A M E S >-------------------------------------------------- This table holds the names of templates and the names of their redirects. Template names must be written exactly as they are named at their templatespace page. This same also applies to redirects. The indexes in this table are not critical but should be short and concise. ]] local template_names = { ['ADB'] = {'Allgemeine Deutsche Biographie', 'Cite ADB'}, ['Butt_Stations'] = {'Butt-Stations', 'Butt-stations'}, ['Cam_Hist_Iran'] = {'Cambridge History of Iran', 'The Cambridge History of Iran'}, ['DNB'] = {'Cite DNB', 'DNB', 'DNB Cite', 'Cite DNBSupp', 'DNBSupp', 'Cite DNB12', 'Cite DNBIE', 'DNB12', 'DNBIE', 'DNBfirst'}, ['ME-ref'] = {'ME-ref', 'Me-ref'}, ['ODB'] = {'ODB', 'Oxford Dictionary of Byzantium'}, ['ODLA'] = {'ODLA', 'Oxford Dictionary of Late Antiquity'}, ['NDB'] = {'Cite NDB', 'NDB'}, ['Iranica'] = {'Encyclopædia Iranica Online', 'Encyclopædia Iranica', 'Encyclopaedia Iranica', 'Cite Encyclopædia Iranica Online'}, } --[[--------------------------< S P E C I A L _ P A T T E R N S >---------------------------------------------- Lua patterns. These are scanned sequentially which costs time and processing far and above the time and processing needed to index into whitelist{}. Do not create a pattern here if a normal whitelist entry or entries can be created. ]] local special_patterns = { 'CITEREFACAD%u%u%u?%u?%d+%u%u?', -- {{Acad}} ID appears to be 2-4 letters, then 3 numbers, then 1-2 letters 'CITEREFAHD%d+', -- {{Cite AHD}} 'CITEREFHistoric_England%d+', -- {{National Heritage List for England}} & {{PastScape}} 'CITEREFHistoric_Environment_Scotland%u%u%u?%u?%d', -- {{Historic Environment Scotland}} %u can be BTL, GLD, HMPA, LB, SM 'CITEREFQHR%d+', -- {{Cite QHR}} 'CITEREF[%d%a_%pöüäß→]+_at_Bach_Digital', -- {{BDh}} 'CITEREF[BR]GBl_[12]%d%d%d%-?I?I?%/%d+', -- {{Cite Austrian gazette}} 'CITEREFStGBl_[12]%d%d%d%/%d+', -- {{Cite Austrian gazette}} 'CITEREFGBlÖ_[12]%d%d%d%/%d+', -- {{Cite Austrian gazette}} } --[[--------------------------< D N B _ S P E C I A L _ P A T T E R N S >-------------------------------------- Lua patterns. Note at special_patterns applies. These for the DNB templates only; these will be tried only when there is a DNB template in the article. Pretty much any author name during the period 1885–1901 inclusive, and 1912. The DNBIE was published in 1903, and Template:DNBIE says that its use is deprecated, but we do not fight that battle here. ]] local DNB_special_patterns = { 'CITEREF%a[%a%-_\']*188[5-9]', -- 1885–1889 'CITEREF%a[%a%-_\']*189%d', -- 1890–1899 'CITEREF%a[%a%-_\']*190[0-1]', -- 1900–1901 'CITEREF%a[%a%-_\']*1903', -- 1903 IE 'CITEREF%a[%a%-_\']*1912', -- 1912 supplement } --[[--------------------------< W H I T E L I S T >------------------------------------------------------------ This is a list of anchor IDs known to be associated with specific wrapper templates. The anchor ID serves as an index into the table. The assigned value is another table that lists the associated template and any redirects. Except for year disambiguators, anchor IDs must have the same form as the anchor creator makes; must be the anchor-encoded form. Remove the year disambiguator. Template names must be written exactly as they are named at their templatespace page. This same also applies to redirects. Module:Footnotes reads the template names left to right so most-commonly-used template or redirect name should appear first. When there are more than one name and when those templates have various anchor IDs the template namelist should be added to the template_names{} table. Note that references to Template:EB1911 are listed under "E" in the alphabetical list below to keep them organized. ]] local whitelist = { ----------< # >---------- ['CITEREF2013_Statistical_Yearbook_of_the_Republic_of_Croatia'] = {'Croatia Yearbook 2013'}, ----------< A >---------- ['CITEREFAGA_1884–1897'] = {'Schubert\'s compositions (references)'}, ['CITEREFATOC2009'] = {'ATOCConnectingCommunitiesReportS10'}, ['CITEREFAbaevBailey1985'] = template_names['Iranica'], ['CITEREFAbbas1988'] = template_names['Iranica'], ['CITEREFAbbas1989'] = template_names['Iranica'], ['CITEREFAbramowitzStegun1983'] = {'Abramowitz Stegun ref'}, ['CITEREFActa_Lipsiensium1723'] = {'Bach\'s compositions (sources)'}, ['CITEREFAdamsFranzosa2009'] = {'Adams Franzosa Introduction to Topology Pure and Applied'}, ['CITEREFAdaschErnstKeim1978'] = {'Adasch Topological Vector Spaces'}, ['CITEREFAffleck1978'] = {'Affleck-On Track'}, ['CITEREFAhlgrimm1969'] = {'Bach\'s compositions (sources)'}, ['CITEREFAhmadiNegahban2013'] = {'Encyclopaedia Islamica'}, ['CITEREFAhrons1927'] = {'Book-Ahrons-British Steam Railway Locomotive'}, ['CITEREFAl-Kindi1912'] = {'The Governors and Judges of Egypt'}, ['CITEREFAlbert_Schumann1886'] = {'Cite ADB'}, ['CITEREFAlden1916'] = {'Shakespeare sonnets bibliography'}, ['CITEREFAldrich1969'] = {'Aldrich-LocosGER7'}, ['CITEREFAleksidze2018'] = template_names['ODLA'], ['CITEREFAlexiou2010'] = {'Cite flatiron'}, ['CITEREFAlgar1983'] = template_names['Iranica'], ['CITEREFAlgar1989'] = template_names['Iranica'], ['CITEREFAlgar1990'] = template_names['Iranica'], ['CITEREFAlgar2003'] = template_names['Iranica'], ['CITEREFAlizadeh1990'] = template_names['Iranica'], ['CITEREFAllamaniPanagiotopoulou1978'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFAllcockDaviesle_FlemingMaskelyne1968'] = {'RCTS-LocosGWR-1'}, ['CITEREFAllenBoddyBrownFry1970'] = {'RCTS-LocosLNER-8A'}, ['CITEREFAllenBoddyBrownFry1971'] = {'RCTS-LocosLNER-8B'}, ['CITEREFAllenBoddyBrownFry1983'] = {'RCTS-LocosLNER-8A'}, ['CITEREFAmanat1998'] = template_names['Iranica'], ['CITEREFAmanat1999'] = template_names['Iranica'], ['CITEREFAmbartsumian2014'] = template_names['Iranica'], ['CITEREFAmerican_Railway_Association1922'] = {'1922 Locomotive Cyclopedia'}, ['CITEREFAnderson1952'] = {'Naval Wars in the Levant 1559–1853'}, ['CITEREFAndo2000'] = template_names['Iranica'], ['CITEREFAngelov2018'] = template_names['ODLA'], ['CITEREFAnwārEIr1985'] = template_names['Iranica'], ['CITEREFArkhangel&#039;skiiPonomarev1984'] = {'Arkhangel\'skii Ponomarev Fundamentals of General Topology Problems and Exercises'}, ['CITEREFArrey_von_Dommer1875'] = {'Cite ADB'}, ['CITEREFAshraf2006'] = template_names['Iranica'], ['CITEREFAslanianBerberian2009'] = template_names['Iranica'], ['CITEREFAsmus1966'] = template_names['NDB'], ['CITEREFAsmussen1985'] = template_names['Iranica'], ['CITEREFAspreas1929'] = {'Great Military and Naval Encyclopaedia'}, ['CITEREFAtkins2007'] = {'Shakespeare sonnets bibliography'}, ['CITEREFAube2011'] = template_names['Iranica'], ['CITEREFAudiKondevWangHuang2017'] = {'NUBASE2016'}, ['CITEREFAvdoyan2018'] = template_names['ODLA'], ['CITEREFAwdry1990'] = {'Awdry-RailCo', 'Carnarvonshire Railway'}, ['CITEREFAzarnoosh2021'] = template_names['Iranica'], ['CITEREFRamelli2018'] = {'Oxford Dictionary of Late Antiquity'},['CITEREFA_History_of_the_Crusades'] = {'Setton-A History of the Crusades'}, ----------< B >---------- ['CITEREFBabinger1962'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFBabinger1978'] = {'Mehmed the Conqueror and His Time'}, ['CITEREFBabinger1992'] = {'Mehmed the Conqueror and His Time'}, ['CITEREFBachAgricola1754'] = {'Bach\'s compositions (sources)'}, ['CITEREFBadura-SkodaBranscombe2008'] = {'Schubert\'s compositions (references)'}, ['CITEREFBahramianHirtensteinGholami2013'] = {'Encyclopaedia Islamica'}, ['CITEREFBalcer1990'] = template_names['Iranica'], ['CITEREFBaldwin1969'] = {'Setton-A History of the Crusades'}, ['CITEREFBaldwin1985'] = {'Setton-A History of the Crusades'}, ['CITEREFBaldwinKazhdan1991'] = template_names['ODB'], ['CITEREFBaldwinTalbot1991'] = template_names['ODB'], ['CITEREFBaltzer1916'] = {'Baltzer-Kolonialbahnen'}, ['CITEREFBanach1932'] = {'Banach Théorie des Opérations Linéaires'}, ['CITEREFBandy2021'] = template_names['Iranica'], ['CITEREFBartusis1991'] = template_names['ODB'], ['CITEREFBaxter1971'] = {'Baxter-BritishLocoCat1'}, ['CITEREFBaxter1977'] = {'Baxter-BritishLocoCat1'}, ['CITEREFBaxter1978'] = {'Baxter-BritishLocoCat2A'}, ['CITEREFBaxter1979'] = {'Baxter-BritishLocoCat2B'}, ['CITEREFBaxter1982'] = {'Baxter-BritishLocoCat3A', 'Baxter-BritishLocoCat3B'}, ['CITEREFBaxter1984'] = {'Baxter-BritishLocoCat4'}, ['CITEREFBaxter1986'] = {'Baxter-BritishLocoCat5A'}, ['CITEREFBaxter1988'] = {'Baxter-BritishLocoCat5B'}, ['CITEREFBaxter2012'] = {'Baxter-BritishLocoCat6'}, ['CITEREFBeattie1986'] = template_names['Iranica'], ['CITEREFBeißwenger1991'] = {'Bach\'s compositions (sources)'}, ['CITEREFBek2001'] = {'Cite Grove'}, ['CITEREFBelke1996'] = {'Tabula Imperii Byzantini'}, ['CITEREFBelkeMersisch1990'] = {'Tabula Imperii Byzantini'}, ['CITEREFBelkeRestle1984'] = {'Tabula Imperii Byzantini'}, ['CITEREFBellini2008'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFBernardini2003'] = template_names['Iranica'], ['CITEREFBernhard_von_Poten1889'] = template_names['ADB'], ['CITEREFBernhard_von_Poten1898'] = template_names['ADB'], ['CITEREFBernjian2008'] = {'Encyclopaedia Islamica'}, ['CITEREFBezilla1980'] = {'Bezilla-PRR-Electric-Traction'}, ['CITEREFBianquis1998'] = {'The Cambridge History of Egypt', 'Cambridge History of Egypt'}, ['CITEREFBickerman1983'] = template_names['Cam_Hist_Iran'], ['CITEREFBierstedt1988'] = {'Bierstedt An Introduction to Locally Convex Inductive Limits'}, ['CITEREFBiran2009'] = template_names['Iranica'], ['CITEREFBirken1976'] = {'Die Provinzen des Osmanischen Reiches'}, ['CITEREFBivar1983'] = template_names['Cam_Hist_Iran'], ['CITEREFBivar2003'] = template_names['Iranica'], ['CITEREFBlair2002'] = template_names['Iranica'], ['CITEREFBlair2021'] = template_names['Iranica'], ['CITEREFBlake1966'] = {'DisraeliRef'}, ['CITEREFBlanken2019'] = {'Bach\'s compositions (sources)'}, ['CITEREFBlankinship1994'] = {'The End of the Jihâd State', 'The End of the Jihad State'}, ['CITEREFBlautSchulze2008'] = {'Bach\'s compositions (sources)'}, ['CITEREFBloom2007'] = {'Cite Routledge Broadway', 'Cite Broadway Routledge', 'Cite Routledge Guide to Broadway', 'Routledge Guide to Broadway'}, ['CITEREFBock1978'] = {'Audie-bock-directors'}, ['CITEREFBoddyBrownFryHennigan1968'] = {'RCTS-LocosLNER-4'}, ['CITEREFBoddyBrownFryHennigan1975'] = {'RCTS-LocosLNER-2B'}, ['CITEREFBoddyBrownFryHennigan1977'] = {'RCTS-LocosLNER-9A', 'RCTS-LocosLNER-9B'}, ['CITEREFBoddyBrownFryHennigan1979'] = {'RCTS-LocosLNER-3A'}, ['CITEREFBoddyBrownHenniganHoole1984'] = {'RCTS-LocosLNER-6C'}, ['CITEREFBoddyBrownHenniganNeve1981'] = {'RCTS-LocosLNER-3B'}, ['CITEREFBoddyBrownNeveYeadon1983'] = {'RCTS-LocosLNER-6B'}, ['CITEREFBoddyFryHenniganHoole1990'] = {'RCTS-LocosLNER-10B'}, ['CITEREFBoddyFryHenniganProud1963'] = {'RCTS-LocosLNER-1'}, ['CITEREFBoddyNeveTeeYeadon1982'] = {'RCTS-LocosLNER-6A'}, ['CITEREFBoddyNeveYeadon1973'] = {'RCTS-LocosLNER-2A'}, ['CITEREFBody1989'] = {'Body-Railways-Vol2'}, ['CITEREFBon1969'] = {'La Morée franque'}, ['CITEREFBonebakker1997'] = template_names['Iranica'], ['CITEREFBonner2010'] = {'New Cambridge History of Islam'}, ['CITEREFBonnett2005'] = {'Bonnett Practical Rail Engineering'}, ['CITEREFBonporti1712'] = {'Bach\'s compositions (sources)'}, ['CITEREFBooth2000'] = {'Shakespeare sonnets bibliography'}, ['CITEREFBorsari1964'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFBossert1914'] = {'Schaff-Herzog'}, ['CITEREFBosworth1968'] = template_names['Cam_Hist_Iran'], ['CITEREFBosworth1975'] = template_names['Cam_Hist_Iran'], ['CITEREFBosworth1983'] = template_names['Iranica'], ['CITEREFBosworth1984'] = template_names['Iranica'], ['CITEREFBosworth1987'] = template_names['Iranica'], ['CITEREFBosworth1988'] = template_names['Iranica'], ['CITEREFBosworth1989'] = template_names['Iranica'], ['CITEREFBosworth1994'] = template_names['Iranica'], ['CITEREFBosworth1995'] = template_names['Iranica'], ['CITEREFBosworth1997'] = template_names['Iranica'], ['CITEREFBosworth1998'] = template_names['Iranica'], ['CITEREFBosworth2000'] = template_names['Iranica'], ['CITEREFBosworth2001'] = template_names['Iranica'], ['CITEREFBosworth2002'] = template_names['Iranica'], ['CITEREFBosworth2003'] = template_names['Iranica'], ['CITEREFBosworth2008'] = template_names['Iranica'], ['CITEREFBosworth2009'] = template_names['Iranica'], ['CITEREFBosworth2010'] = template_names['Iranica'], ['CITEREFBosworth2011'] = template_names['Iranica'], ['CITEREFBosworthCrane1984'] = template_names['Iranica'], ['CITEREFBottoMitchell2002'] = {'Cite ATT Broadway', 'Cite At This Theatre Broadway', 'Cite Broadway At This Theatre', 'Cite Broadway ATT'}, ['CITEREFBourbaki1987'] = {'Bourbaki Topological Vector Spaces'}, ['CITEREFBourbaki1989'] = {'Bourbaki General Topology Part I Chapters 1-4', 'Bourbaki General Topology Part II Chapters 5-10', 'Bourbaki Algebra I Chapters 1-3 Springer'}, ['CITEREFBourbaki1994'] = {'Bourbaki EHM'}, ['CITEREFBowen1928'] = {'The Life and Times of Ali ibn Isa'}, ['CITEREFBowmanCameronGarnsey2005'] = {'Cambridge Ancient History'}, ['CITEREFBoyce1983'] = template_names['Iranica'], ['CITEREFBoyce1986'] = template_names['Iranica'], ['CITEREFBoyce1989'] = template_names['Iranica'], ['CITEREFBoyce2000'] = template_names['Iranica'], ['CITEREFBoyce2009'] = template_names['Iranica'], ['CITEREFBoyd1970'] = {'Boyd-MidWales'}, ['CITEREFBoyd1975'] = {'Boyd-FR1'}, ['CITEREFBoyd1985'] = {'Boyd-NCaerns2Penrhyn'}, ['CITEREFBoyd1986'] = {'Boyd-NCaerns3Dinorwic'}, ['CITEREFBoyd1988'] = {'Boyd-SCaerns1'}, ['CITEREFBoyd1989'] = {'Boyd-SCaerns2'}, ['CITEREFBoyd1990'] = {'Boyd-NCaerns1'}, ['CITEREFBradshaw1968'] = {'Bradshaw-1910April'}, ['CITEREFBradshaw1985'] = {'Bradshaw-1922July'}, ['CITEREFBradshaw2011'] = {'Bradshaw-1895December'}, ['CITEREFBradshaw2012'] = {'Bradshaw-1850March'}, ['CITEREFBrand1968'] = {'Byzantium Confronts the West'}, ['CITEREFBrand1991'] = {'DBI', 'ODB', 'Oxford Dictionary of Byzantium'}, ['CITEREFBray2010'] = {'Bray-SDJR'}, ['CITEREFBrett2010'] = {'New Cambridge History of Islam'}, ['CITEREFBriant1985'] = template_names['Iranica'], ['CITEREFBrosius2000'] = template_names['Iranica'], ['CITEREFBrown2000'] = template_names['Iranica'], ['CITEREFBrown2008'] = {'The Cambridge History of the Byzantine Empire'}, ['CITEREFBrunner1975'] = template_names['Cam_Hist_Iran'], ['CITEREFBrunner1983'] = template_names['Cam_Hist_Iran'], ['CITEREFBrunner1984'] = template_names['Iranica'], ['CITEREFBrunner1986'] = template_names['Iranica'], ['CITEREFBryan1886'] = {'Bryan (3rd edition)'}, ['CITEREFBryan1889'] = {'Bryan (3rd edition)'}, ['CITEREFBuhle1909'] = {'Bach\'s compositions (sources)'}, ['CITEREFBulliet1984'] = template_names['Iranica'], ['CITEREFBulookbashiNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFBunbury1857'] = {'DGRG'}, ['CITEREFBurant1987'] = {'Cite DCB'}, ['CITEREFBurch1911'] = {'Burch Electric Traction'}, ['CITEREFBurke1866'] = {'O\'Donnell family tree'}, ['CITEREFBurn1985'] = template_names['Cam_Hist_Iran'], ['CITEREFBurrowsWallace1999'] = {'Cite gotham'}, ['CITEREFBury1911'] = {'The Imperial Administrative System of the Ninth Century'}, ['CITEREFBusse1975'] = template_names['Cam_Hist_Iran'], ['CITEREFBusse1982'] = template_names['Iranica'], ['CITEREFButcherNicholson2018'] = template_names['ODLA'], ['CITEREFButt1995'] = template_names['Butt_Stations'], ['CITEREFBöwering1995'] = template_names['Iranica'], ['CITEREFBürgelMottahedeh1988'] = template_names['Iranica'], ----------< C >---------- ['CITEREFCIC1983'] = {'CIC1983bib'}, ['CITEREFCalifornia1988'] = {'CA-Rail Passenger Development Plan-1988'}, ['CITEREFCalmard1988'] = template_names['Iranica'], ['CITEREFCalmard1999'] = template_names['Iranica'], ['CITEREFCaltrans1984'] = {'Countrystudy'}, ['CITEREFCameronWard-PerkinsWhitby2000'] = {'Cambridge Ancient History'}, ['CITEREFCanepa2018'] = template_names['ODLA'], ['CITEREFCanny2008'] = {'O\'Donnell family tree'}, ['CITEREFCappelCutlerKazhdan1991'] = template_names['ODB'], ['CITEREFCarl_von_Prantl1879'] = {'Cite ADB'}, ['CITEREFCarlson2010'] = {'Dlmf'}, ['CITEREFCaro1974'] = {'Cite Power Broker'}, ['CITEREFCarpenter1977'] = template_names['ME-ref'], ['CITEREFCarpenter1981'] = template_names['ME-ref'], ['CITEREFCarra_de_VauxHodgson1965'] = {'EI2'}, ['CITEREFCarter2006'] = {'Carter-RailwaysMotivePowerArgentina'}, ['CITEREFCasserley1968'] = {'Casserley-joint'}, ['CITEREFCasserleyJohnston1966'] = {'Casserley-LocoGrouping3'}, ['CITEREFCasserleyJohnston1974'] = {'Casserley-LocoGrouping3', 'Casserley-LocoGrouping2', '0-7110-0554-0'}, ['CITEREFCasway1984'] = {'O\'Donnell family tree'}, ['CITEREFCavanna_Ciappina2001'] = {'DBI'}, ['CITEREFCawley2001'] = {'Medieval Lands by Charles Cawley', 'MLCC'}, ['CITEREFCawley2001'] = {'Medieval Lands by Charles Cawley'}, ['CITEREFCawley2010'] = {'MLCC'}, ['CITEREFCawley2011'] = {'MLCC'}, ['CITEREFChaléardChanson-JabeurBéranger2006'] = {'Chaléard-Le cdf en Afrique'}, ['CITEREFChambers1728'] = {'Cyclopaedia 1728'}, ['CITEREFChasiotis1975'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFChaumont1985'] = template_names['Iranica'], ['CITEREFChaumont1986'] = template_names['Iranica'], ['CITEREFChaumont1987'] = template_names['Iranica'], ['CITEREFChaumont1990'] = template_names['Iranica'], ['CITEREFChaumontSchippmann1988'] = template_names['Iranica'], ['CITEREFCheyneBlack1899'] = {'Biblica', 'Cite Biblica'}, ['CITEREFCheyneBlack1899–1903'] = {'Cite Biblica'}, ['CITEREFCheyneBlack1901'] = {'Cite Biblica'}, ['CITEREFCheyneBlack1902'] = {'Cite Biblica'}, ['CITEREFCheyneBlack1903'] = {'Cite Biblica'}, ['CITEREFChisholm1922'] = {'EB1922', 'Cite EB1922'}, ['CITEREFChittick1997'] = template_names['Iranica'], ['CITEREFChkeidze2001'] = template_names['Iranica'], ['CITEREFChoniates1984'] = {'O City of Byzantium'}, ['CITEREFChrista_Jost1999'] = template_names['NDB'], ['CITEREFChung1994'] = {'Country study'}, ['CITEREFChurchmanHurst2001'] = {'Churchman & Hurst Railways of New Zealand'}, ['CITEREFChurchman_&amp;_Hurst2001'] = {'Churchman & Hurst Railways of New Zealand'}, ['CITEREFChurella2013'] = {'Churella-PRR-1'}, ['CITEREFClementsMcMahon2008'] = {'ClementsMcMahon-GSR Locomotives'}, ['CITEREFClinker1978'] = {'Clinker-Stations'}, ['CITEREFClinker1988'] = {'Clinker-Stations'}, ['CITEREFCoates1990'] = {'Coates-Reading'}, ['CITEREFColbyWilliams1916'] = {'New International Encyclopedia', 'NIE'}, ['CITEREFColledgeWarlow2006'] = {'Colledge', 'Cite Colledge2006'}, ['CITEREFColledgeWarlow2010'] = {'Cite Colledge2010'}, ['CITEREFCollins2016'] = {'Cite Collins 2016'}, ['CITEREFConolly1998'] = {'IanAllan-PreGroup-Atlas1998'}, ['CITEREFConway1990'] = {'Conway A Course in Functional Analysis'}, ['CITEREFCosentino2008'] = {'DBI'}, ['CITEREFCoulthard-Clark2002'] = {'Australian Dictionary of Biography'}, ['CITEREFCousin1910'] = {'A Short Biographical Dictionary of English Literature', 'Cite SBDEL'}, ['CITEREFCox1967'] = {'Cox-Upper Darby'}, ['CITEREFCox2011'] = {'Cox-Dixie'}, ['CITEREFCrevier1993'] = {'Crevier 1993'}, ['CITEREFCrockett2007'] = {'Australian Dictionary of Biography'}, ['CITEREFCroke2018'] = template_names['ODLA'], ['CITEREFCrone1980'] = {'Slaves on Horses'}, ['CITEREFCronin2011'] = template_names['Iranica'], ['CITEREFCroughtonKidnerYoung1982'] = {'Croughton-PrivateStations'}, ['CITEREFCruickshanks1970'] = {'HistoryofParliament'}, ['CITEREFCudahy2002'] = {'Cudahy-Hudson'}, ['CITEREFCudahy2003'] = {'Cudahy-Subways'}, ['CITEREFCurta2006'] = {'Southeastern Europe in the Middle Ages, 500–1250'}, ----------< D >---------- ['CITEREFDBI'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFDZS2015'] = {'Croatia Yearbook 2015'}, ['CITEREFDadelsen1957'] = {'Bach\'s compositions (sources)'}, ['CITEREFDaftary1990'] = {'Daftary-The Ismailis'}, ['CITEREFDaftary2003'] = template_names['Iranica'], ['CITEREFDaftary2007'] = {'Daftary-The Ismailis'}, ['CITEREFDaftary2015'] = template_names['Iranica'], ['CITEREFDaiber1988'] = template_names['Iranica'], ['CITEREFDandamayevShahbaziLecoq1986'] = template_names['Iranica'], ['CITEREFDaniel2000'] = template_names['Iranica'], ['CITEREFDaniel2010'] = {'New Cambridge History of Islam'}, ['CITEREFDanielsDench1963'] = {'Daniels-NoMore'}, ['CITEREFDanielsDench1973'] = {'Daniels-NoMore'}, ['CITEREFDanner1975'] = template_names['Cam_Hist_Iran'], ['CITEREFDarleyCanepa2018'] = {'Oxford Dictionary of Late Antiquity'}, ['CITEREFDaryaee2009'] = template_names['Iranica'], ['CITEREFDaryaee2018'] = template_names['ODLA'], ['CITEREFDaryaeeCanepa2018'] = template_names['ODLA'], ['CITEREFDavid1961'] = {'Bach\'s compositions (sources)'}, ['CITEREFDavidson2010'] = {'HistoryofParliament'}, ['CITEREFDavidsonThrush2010'] = {'HistoryofParliament'}, ['CITEREFDavies1996'] = {'Davies-PLMLocoList'}, ['CITEREFDavies1997'] = {'Davies-NordLocoList'}, ['CITEREFDavies2001'] = {'Davies-EstLocoList3', 'Davies-ÉtatLocoList'}, ['CITEREFDavies2003'] = {'Davies-SNCFLocoList'}, ['CITEREFDaviesFirthLuckingThomas1966'] = {'RCTS-LocosGWR-10'}, ['CITEREFDavud2018'] = {'Encyclopaedia Islamica'}, ['CITEREFDavudNazerian2008'] = {'Encyclopaedia Islamica'}, ['CITEREFDe_Negri1997'] = {'DBI'}, ['CITEREFDemircan2010'] = {'TDV Encyclopedia of Islam'}, ['CITEREFDeutsch1951'] = {'Schubert\'s compositions (references)'}, ['CITEREFDeutsch1978'] = {'Schubert\'s compositions (references)'}, ['CITEREFDeutsche_Autos,_Band_2,2001'] = {'Deutsche Autos-2'}, ['CITEREFDeutsche_Autos,_Band_3,2001'] = {'Deutsche Autos-3'}, ['CITEREFDeutsche_Autos,_Band_4,2001'] = {'Deutsche Autos-4'}, ['CITEREFDeutsche_Autos,_Band_5,2001'] = {'Deutsche Autos-5'}, ['CITEREFDeutsche_Autos,_Band_6,2001'] = {'Deutsche Autos-6'}, ['CITEREFDewick2005'] = {'Dewick-Atlas'}, ['CITEREFDiamonstein-Spielvogel2011'] = {'Cite landmarks'}, ['CITEREFDickens2018'] = template_names['ODLA'], ['CITEREFDirksen1998'] = {'Bach\'s compositions (sources)'}, ['CITEREFDirksen2010'] = {'Bach\'s compositions (sources)'}, ['CITEREFDirksen2016'] = {'Bach\'s compositions (sources)'}, ['CITEREFDixmier1984'] = {'Dixmier General Topology'}, ['CITEREFDoerfer1989'] = template_names['Iranica'], ['CITEREFDoganis1930'] = {'Great Military and Naval Encyclopaedia'}, ['CITEREFDoleckiMynard2016'] = {'Dolecki Mynard Convergence Foundations Of Topology'}, ['CITEREFDolkart1998'] = {'Cite morningside'}, ['CITEREFDonner1995'] = template_names['Iranica'], ['CITEREFDonohue2003'] = {'The Buwayhid Dynasty in Iraq'}, ['CITEREFDorin1972'] = {'Dorin-North Western'}, ['CITEREFDow1962'] = {'Dow-GC2'}, ['CITEREFDow1965'] = {'Dow-GC3'}, ['CITEREFDow1985'] = {'Dow-GC1'}, ['CITEREFDowney2007'] = {'Downey-Chicago'}, ['CITEREFDrechsler2005'] = template_names['Iranica'], ['CITEREFDrummond1964'] = {'HistoryofParliament'}, ['CITEREFDrury1985'] = {'Drury Historical Guide 1985'}, ['CITEREFDrury1993'] = {'Drury-North American Steam'}, ['CITEREFDuchesne-Guillemin1994'] = template_names['Iranica'], ['CITEREFDugundji1966'] = {'Dugundji Topology'}, ['CITEREFDuke1995'] = {'Duke-Santa Fe-1'}, ['CITEREFDukeKeilty1990'] = {'Duke-RDC'}, ['CITEREFDumbarton_Oaks_Hagiography_Database'] = {'Dumbarton Oaks Hagiography Database'}, ['CITEREFDunbar1969'] = {'Dunbar-Railroads'}, ['CITEREFDuncan-Jones2010'] = {'Shakespeare sonnets bibliography'}, ['CITEREFDunlop1895'] = {'O\'Donnell family tree'}, ['CITEREFDunlop1985'] = template_names['Iranica'], ['CITEREFDunn2013'] = {'Dunn-Comeng-5'}, ['CITEREFDurand-Guédy2008'] = template_names['Iranica'], ['CITEREFDurand-Guédy2010'] = template_names['Iranica'], ['CITEREFDurand-Guédy2013'] = {'Encyclopaedia Islamica'}, ['CITEREFDurham1998'] = {'California\'s Geographic Names'}, ['CITEREFDurrant1972'] = {'Durrant-Steam Locos Eastern Europe'}, ['CITEREFDurrant1981'] = {'Durrant-Garratt-Rev'}, ['CITEREFDurrantLewisJorgensen1981'] = {'Durrant-SteamAfrica'}, ['CITEREFDömlingKohlhase1971'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürr1952'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürr1954'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürr1987'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürrJones2006'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürrKobayashi1998'] = {'Bach\'s compositions (sources)'}, ['CITEREFde_Blois2000'] = template_names['Iranica'], ['CITEREFde_Planhol1987'] = template_names['Iranica'], ['CITEREFde_Planhol1988'] = template_names['Iranica'], ----------< E >---------- ['CITEREFEIr.1994'] = template_names['Iranica'], ['CITEREFEarle2018'] = {'Gymnosperm Database'}, ['CITEREFEbata2019'] = {'BDh'}, ['CITEREFEbata2020'] = {'BDh'}, ['CITEREFEbrahimKhodaverdian2018'] = {'Encyclopaedia Islamica'}, ['CITEREFEdwards1995'] = {'Edwards Functional Analysis Theory and Applications'}, ['CITEREFEichberg1976'] = {'Bach\'s compositions (sources)'}, ['CITEREFEilers1983'] = template_names ['Cam_Hist_Iran'], ['CITEREFEkbal1991'] = template_names['Iranica'], ['CITEREFEl-Hibri2010'] = {'New Cambridge History of Islam'}, ['CITEREFEldredgeHorenstein2014'] = {'Cite concrete'}, ['CITEREFElsholz1982'] = {'Schubert\'s compositions (references)'}, ['CITEREFElwell-Sutton1984'] = template_names['Iranica'], ['CITEREFEppstein1966'] = {'Bach\'s compositions (sources)'}, ['CITEREFEppstein1982'] = {'Bach\'s compositions (sources)'}, ['CITEREFEquasis'] = {'Csr', 'Cite ship register'}, ['CITEREFEuDaly2009'] = {'Complete Book of North American Railroading'}, ['CITEREFEuDalySchaferJessupBoyd2009'] = {'Complete Book of North American Railroading'}, ----------< F >---------- ['CITEREFFacella2021'] = template_names['Iranica'], ['CITEREFFang1943'] = {'Cite ECCP'}, ['CITEREFFarinella2001'] = {'DBI'}, ['CITEREFFatehi-NezhadAzarnooshNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFFatehi-nezhadRahimi2008'] = {'Encyclopaedia Islamica'}, ['CITEREFFeder1958'] = {'Bach\'s compositions (sources)'}, ['CITEREFFederal_Writers&#039;_Project1939'] = {'Cite fednyc'}, ['CITEREFFelixMadelung1995'] = template_names['Iranica'], ['CITEREFFernandez1983'] = {'Fernandez1983'}, ['CITEREFFesharaki2015'] = {'Encyclopaedia Islamica'}, ['CITEREFFiaccadori1991'] = template_names['ODB'], ['CITEREFFikratUmar2008'] = template_names['Iranica'], ['CITEREFFine1991'] = {'The Early Medieval Balkans'}, ['CITEREFFine1994'] = {'The Late Medieval Balkans'}, ['CITEREFFletcher,_Great_Tank_Scandal'] = {'Book-Fletcher-Great Tank Scandal'}, ['CITEREFFletcher,_Universal_Tank'] = {'Book-Fletcher-Universal Tank'}, ['CITEREFFloor1992'] = template_names['Iranica'], ['CITEREFFloor2005'] = template_names['Iranica'], ['CITEREFFlora_of_North_America'] = {'EFloras'}, ['CITEREFFlora_of_North_America2009'] = {'EFloras'}, ['CITEREFFluckMarshallWilson1996'] = {'FluMarWil-LocRailCR'}, ['CITEREFFonstad1991'] = template_names['ME-ref'], ['CITEREFForkelTerry1920'] = {'Bach\'s compositions (sources)'}, ['CITEREFFornaçon,_Siegfried1957'] = template_names['NDB'], ['CITEREFForrestal1999'] = {'Forrestal-Wineries'}, ['CITEREFForster1990'] = {'Cite DCB'}, ['CITEREFFoss1991'] = template_names['ODB'], ['CITEREFFoster1971'] = template_names['ME-ref'], ['CITEREFFoster1996'] = {'Foster-Field Guide'}, ['CITEREFFrailey2010'] = {'Frailey-Twilight'}, ['CITEREFFranke1994'] = {'Cite Cambridge History of China'}, ['CITEREFFranz_Schnorr_von_Carolsfeld1883'] = {'Cite ADB'}, ['CITEREFFriedrich_Wilhelm_Bautz1975'] = {'BBKL'}, ['CITEREFFriedrich_Wilhelm_Bautz1990'] = {'BBKL'}, ['CITEREFFry1964'] = {'RCTS-LocosLNER-7'}, ['CITEREFFry1966'] = {'RCTS-LocosLNER-5'}, ['CITEREFFrye1975'] = template_names['Cam_Hist_Iran'], ['CITEREFFrye1983'] = template_names['Cam_Hist_Iran'], ['CITEREFFrye2004'] = template_names['Iranica'], ['CITEREFFubini2012'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFFudenbergTirole1991'] = {'Cite Fudenberg Tirole 1991'}, ['CITEREFFultonHarris1991'] = {'Fulton-Harris'}, ----------< G >---------- ['CITEREFGarakaniBrown2013'] = {'Encyclopaedia Islamica'}, ['CITEREFGardner2005'] = {'MSW3 Microbiotheria'}, ['CITEREFGardoni2015'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFGareyJohnson1979'] = {'Garey-Johnson'}, ['CITEREFGarsoian2000'] = template_names['Iranica'], ['CITEREFGarsoian2004'] = template_names['Iranica'], ['CITEREFGarsoian2005'] = template_names['Iranica'], ['CITEREFGarth2003'] = template_names['ME-ref'], ['CITEREFGazette34205'] = {'London Gazette'}, ['CITEREFGazette34339'] = {'London Gazette'}, ['CITEREFGazette34390'] = {'London Gazette'}, ['CITEREFGazette34427'] = {'London Gazette'}, ['CITEREFGazette34558'] = {'London Gazette'}, ['CITEREFGazette34870'] = {'London Gazette'}, ['CITEREFGazette34978'] = {'London Gazette'}, ['CITEREFGazette34989'] = {'London Gazette'}, ['CITEREFGazette35037'] = {'London Gazette'}, ['CITEREFGazette35107'] = {'London Gazette'}, ['CITEREFGazette35134'] = {'London Gazette'}, ['CITEREFGazette35284'] = {'London Gazette'}, ['CITEREFGazette37560'] = {'London Gazette'}, ['CITEREFGazette37590'] = {'London Gazette'}, ['CITEREFGazette37598'] = {'London Gazette'}, ['CITEREFGazette37610'] = {'London Gazette'}, ['CITEREFGazette38020'] = {'London Gazette'}, ['CITEREFGazette38611'] = {'London Gazette'}, ['CITEREFGeanakoplos1959'] = {'Emperor Michael Palaeologus and the West'}, ['CITEREFGeorg_von_Dadelsen1953'] = template_names['NDB'], ['CITEREFGhanoonparvar1989'] = template_names['Iranica'], ['CITEREFGhereghlou2009'] = template_names['Iranica'], ['CITEREFGhereghlou2016'] = template_names['Iranica'], ['CITEREFGhulamiyan2015'] = template_names['Iranica'], ['CITEREFGhulamiyan2015'] = {'Encyclopaedia Islamica'}, ['CITEREFGiannasi1975'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFGibb1923'] = {'The Arab Conquests in Central Asia'}, ['CITEREFGignoux1983'] = template_names['Iranica'], ['CITEREFGignoux1994'] = template_names['Iranica'], ['CITEREFGil1997'] = {'A History of Palestine, 634-1099', 'A History of Palestine, 634–1099'}, ['CITEREFGillham2001'] = {'Gillham-Waterloo-City'}, ['CITEREFGilliland1969'] = {'Gilliland'}, ['CITEREFGilliland1994'] = {'Pop Chronicles 40s'}, ['CITEREFGilliverMarshallWeiner2006'] = template_names['ME-ref'], ['CITEREFGilmanPeckColby1905'] = {'Cite NIE', 'New International Encyclopedia', 'NIE'}, ['CITEREFGilmanPeckColby1916'] = {'New International Encyclopedia', 'NIE'}, ['CITEREFGiunashvili2016'] = template_names['Iranica'], ['CITEREFGleaves1921'] = {'Gleaves'}, ['CITEREFGlischinski1997'] = {'Glischinski-Santa Fe'}, ['CITEREFGlöckner1983'] = {'Bach\'s compositions (sources)'}, ['CITEREFGoldberg1981'] = {'Goldberg-Amtrak'}, ['CITEREFGordon2001'] = {'Gordon-The Breaking of a Thousand Swords'}, ['CITEREFGraham1974'] = {'Cite DCB'}, ['CITEREFGrant1994'] = {'Grant-Death'}, ['CITEREFGrant2010'] = {'Grant-Twilight'}, ['CITEREFGrant2017'] = {'Grant-RailCo'}, ['CITEREFGrassi2018'] = template_names['Iranica'], ['CITEREFGray1986'] = template_names['Cam_Hist_Iran'], ['CITEREFGreenlaw2007'] = {'Greenlaw-Via Rail'}, ['CITEREFGregory1991'] = template_names['ODB'], ['CITEREFGregoryŠevčenko1991'] = template_names['ODB'], ['CITEREFGrete_Schemann1957'] = template_names['NDB'], ['CITEREFGrey2002'] = {'Australian Dictionary of Biography'}, ['CITEREFGrierson1903'] = {'Cite LSI', 'LSI', 'Linguistic Survey of India'}, ['CITEREFGrierson1908'] = {'Cite LSI', 'LSI', 'Linguistic Survey of India'}, ['CITEREFGrierson1919'] = {'Cite LSI', 'LSI', 'Linguistic Survey of India'}, ['CITEREFGrierson1967'] = {'Cite LSI', 'LSI', 'Linguistic Survey of India'}, ['CITEREFGriffith1991'] = template_names['ODB'], ['CITEREFGriffithsSmith1999'] = {'Griffiths-Sheds1'}, ['CITEREFGriffithsSmith2000'] = {'Griffiths-Sheds2'}, ['CITEREFGrothendieck1955'] = {'Grothendieck Produits Tensoriels Topologiques et Espaces Nucléaires'}, ['CITEREFGrothendieck1973'] = {'Grothendieck Topological Vector Spaces'}, ['CITEREFGrothendieckDieudonné1960'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1961'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1963'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1964'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1965'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1966'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1967'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1971'] = {'EGA'}, ['CITEREFGroves2005'] = {'MSW3 Primates', 'MSW3 Groves'}, ['CITEREFGrubb2005'] = {'MSW3 Artiodactyla'}, ['CITEREFGuilland1967'] = {'Recherches sur les institutions byzantines'}, ['CITEREFGulino2005'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFGunzburg1984'] = {'Gunzburg-History WAGR Steam'}, ['CITEREFGurneyNabavi1993'] = template_names['Iranica'], ['CITEREFGutas1987'] = template_names['Iranica'], ['CITEREFGvakharia2001'] = template_names['Iranica'], ['CITEREFGüner1997'] = {'TDV Encyclopedia of Islam'}, ----------< H >---------- ['CITEREFHaarer2018'] = template_names['ODLA'], ['CITEREFHabibi2021'] = template_names['Iranica'], ['CITEREFHadidi2000'] = template_names['Iranica'], ['CITEREFHaji2008'] = template_names['Iranica'], ['CITEREFHaldon1999'] = {'Warfare, State and Society in the Byzantine World, 565–1204'}, ['CITEREFHalliday1985'] = {'Halliday-AustWineCompend'}, ['CITEREFHalliday2008'] = {'Halliday-JHWAtlasAust2008'}, ['CITEREFHalliday2009'] = {'Halliday-AustWineEncyc'}, ['CITEREFHalm1998'] = template_names['Iranica'], ['CITEREFHalpenny1990'] = {'Canadabio'}, ['CITEREFHambly1990'] = template_names['Cam_Hist_Iran'], ['CITEREFHambly1991'] = template_names['Cam_Hist_Iran'], ['CITEREFHammondAnderson1993'] = template_names['ME-ref'], ['CITEREFHammondScull1995'] = template_names['ME-ref'], ['CITEREFHammondScull2005'] = template_names['ME-ref'], ['CITEREFHammondScull2006a'] = template_names['ME-ref'], ['CITEREFHammondScull2006b'] = template_names['ME-ref'], ['CITEREFHanaway1988'] = template_names['Iranica'], ['CITEREFHanaway1989'] = template_names['Iranica'], ['CITEREFHanawayLewisohn2004'] = template_names['Iranica'], ['CITEREFHans_Heinrich_Borcherdt1955'] = template_names['NDB'], ['CITEREFHans_Knudsen1972'] = template_names['NDB'], ['CITEREFHansen1988'] = {'Book-Hansen-US Nuclear Weapons'}, ['CITEREFHansman1991'] = template_names['Iranica'], ['CITEREFHartshorne1977'] = {'Hartshorne AG'}, ['CITEREFHassanpour1989'] = template_names['Iranica'], ['CITEREFHassanpour1995'] = template_names['Iranica'], ['CITEREFHasumi2003'] = {'Hasumi-shiguehiko-ozu-2003'}, ['CITEREFHaswell-Smith2004'] = {'Haswell-Smith'}, ['CITEREFHaugic1908'] = {'Schaff-Herzog'}, ['CITEREFHawting1987'] = {'The First Dynasty of Islam'}, ['CITEREFHawting2000'] = {'The First Dynasty of Islam'}, ['CITEREFHaynes2011'] = {'RubberBible92nd'}, ['CITEREFHeinichen1728'] = {'Bach\'s compositions (sources)'}, ['CITEREFHeinrich_Welti1890'] = {'Cite ADB'}, ['CITEREFHelgen2005'] = {'MSW3 Scandentia'}, ['CITEREFHellmann1965'] = {'Bach\'s compositions (sources)'}, ['CITEREFHenrici1725'] = {'Bach\'s compositions (sources)'}, ['CITEREFHenryOrsmond1928'] = {'Raiatea family tree'}, ['CITEREFHermann_Palm1876'] = {'Cite ADB'}, ['CITEREFHerr2000'] = {'Herr-LN'}, ['CITEREFHeschel2007'] = {'Encyclopaedia Judaica', 'Cite EJ', 'Cite Encyclopaedia Judaica'}, ['CITEREFHewsen1988'] = template_names['Iranica'], ['CITEREFHidyHidyScottHofsummer2004'] = {'Hidy-Great Northern'}, ['CITEREFHildHellenkemper1990'] = {'Tabula Imperii Byzantini'}, ['CITEREFHildHellenkemper1994'] = {'Tabula Imperii Byzantini'}, ['CITEREFHildRestle1981'] = {'Tabula Imperii Byzantini'}, ['CITEREFHillenbrand1986'] = template_names['Iranica'], ['CITEREFHills,_Power_from_Steam'] = {'Book-Hills-Power from Steam'}, ['CITEREFHills1989'] = {'Book-Hills-Power from Steam'}, ['CITEREFHilmarJestremski2004'] = {'Schubert\'s compositions (references)'}, ['CITEREFHilton1980'] = {'Hilton-Amtrak'}, ['CITEREFHilton1990'] = {'Hilton Narrow Gauge'}, ['CITEREFHiltonDue1960'] = {'Hilton-Interurban'}, ['CITEREFHinton1986'] = {'HistoryofParliament'}, ['CITEREFHirsch1906'] = {'Cite JE1906'}, ['CITEREFHistoric_Environment_Scotland'] = {'Canmore'}, ['CITEREFHistoric_Environment_Scotland1972'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_Scotland1976'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_Scotland2020'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_Scotland:_Rusco_Tower2020'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_ScotlandLB33744'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_ScotlandLB50114'] = {'Historic Environment Scotland'}, ['CITEREFHob.'] = {'Schubert\'s compositions (references)'}, ['CITEREFHoffmanSmith2005'] = {'MSW3 Lagomorpha'}, ['CITEREFHoffmann1738'] = {'Bach\'s compositions (sources)'}, ['CITEREFHofmann1983'] = {'Bach\'s compositions (sources)'}, ['CITEREFHofmann1987'] = {'Bach\'s compositions (sources)'}, ['CITEREFHofmann1999'] = {'Bach\'s compositions (sources)'}, ['CITEREFHolland1972'] = {'Holland-Vol 2'}, ['CITEREFHolland1988'] = {'Cite DCB'}, ['CITEREFHolland2001'] = {'Holland-Classic'}, ['CITEREFHollingsworth1980'] = {'Hollingsworth-Atlas-Rigby'}, ['CITEREFHollingsworth1991'] = template_names['ODB'], ['CITEREFHollingsworthCutler1991'] = template_names['ODB'], ['CITEREFHolmgren2003'] = {'EFloras'}, ['CITEREFHoltBiddle1986'] = {'Holt-NorthWest'}, ['CITEREFHolton1989'] = {'Holton-Reading-1'}, ['CITEREFHonigmann1935'] = {'Byzance et les Arabes'}, ['CITEREFHopley1983'] = {'Australian Dictionary of Biography'}, ['CITEREFHort1911'] = {'DCBL'}, ['CITEREFHorváth1966'] = {'Horváth Topological Vector Spaces and Distributions Volume 1 1966'}, ['CITEREFHosseini2017'] = template_names['Iranica'], ['CITEREFHounshell1984'] = {'Hounshell1984'}, ['CITEREFHudson1997'] = {'Country study'}, ['CITEREFHughes1990'] = {'Hughes-IndianLocos1'}, ['CITEREFHughes1992'] = {'Hughes-IndianLocos2'}, ['CITEREFHughes1994'] = {'Hughes-IndianLocos3'}, ['CITEREFHughes1996'] = {'Hughes-IndianLocos4'}, ['CITEREFHummel1943'] = {'Cite ECCP'}, ['CITEREFHumphreys2018'] = template_names['ODLA'], ['CITEREFHunter-Crawley2018'] = template_names['ODLA'], ['CITEREFHunter2008'] = {'Country study'}, ['CITEREFHutter2009'] = template_names['Iranica'], ['CITEREFHutterer2005'] = {'MSW3 Soricomorpha'}, ['CITEREFHütter2012'] = {'Hütter-50bis53'}, ['CITEREFHütter2015'] = {'Hütter-54bis59'}, ['CITEREFHütter2021'] = {'Hütter-60bis91'}, ----------< I >---------- ['CITEREFIbn_Khallikan1843'] = {'Ibn Khallikan\'s Biographical Dictionary'}, ['CITEREFImber2002'] = {'Imber-The Ottoman Empire, 1300–1650'}, ['CITEREFInalcik1989'] = {'Setton-A History of the Crusades'}, ['CITEREFIranica:_Bahrām'] = template_names['Iranica'], ['CITEREFIrvine2006'] = template_names['Iranica'], ['CITEREFIshino1998'] = {'Teishajo'}, ['CITEREFIshkevariNejad2008'] = {'Encyclopaedia Islamica'}, ['CITEREFIvey1919'] = {'Ivey-Marquette'}, ----------< J >---------- ['CITEREFJackson1908'] = {'Schaff-Herzog'}, ['CITEREFJackson1988'] = template_names['Iranica'], ['CITEREFJackson1989'] = template_names['Iranica'], ['CITEREFJackson1995'] = {'Cite enc-nyc'}, ['CITEREFJackson2010'] = {'Cite enc-nyc2'}, ['CITEREFJacksonMelville2001'] = template_names['Iranica'], ['CITEREFJacobs1904'] = {'Cite Jewish Encyclopedia'}, ['CITEREFJarchow1981'] = {'Jarchow Locally Convex Spaces'}, ['CITEREFJavadiBurrill1988'] = template_names['Iranica'], ['CITEREFJohn_O&#039;Donovan1856'] = {'Cite AFM'}, ['CITEREFJohnstonWelshSchafer2001'] = {'Johnston-Streamliner'}, ['CITEREFJones2011'] = {'Cite EPD'}, ['CITEREFJordan2002'] = {'Jordan-WineWABest'}, ['CITEREFJoshi1983'] = {'Joshi Introduction to General Topology'}, ['CITEREFJoslen2003'] = {'Joslen-OOB'}, ['CITEREFJowett1867'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFJowett1989'] = {'Jowett-Atlas', 'Carnarvonshire Railway'}, ['CITEREFJowett2000'] = {'Jowett-Nationalised'}, ['CITEREFJullien2018'] = template_names['ODLA'], ['CITEREFJupp1986'] = {'HistoryofParliament'}, ----------< K >---------- ['CITEREFK.'] = {'Schubert\'s compositions (references)'}, ['CITEREFKadinsky2016'] = {'Cite Hidden Waters NYC'}, ['CITEREFKaegi1991'] = template_names['ODB'], ['CITEREFKamaly2006'] = template_names['Iranica'], ['CITEREFKamp1981'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFKang2008'] = {'Country study'}, ['CITEREFKaramatiMelvin-Koushki2021'] = template_names['Iranica'], ['CITEREFKaramatiMelvin-Koushki2021'] = {'Encyclopaedia Islamica'}, ['CITEREFKarimi-Hakkak1997'] = template_names['Iranica'], ['CITEREFKarimiMaghsoodi2013'] = {'Encyclopaedia Islamica'}, ['CITEREFKarl_Frohnmeyer1953'] = template_names['NDB'], ['CITEREFKarnow1989'] = {'Cite-Karnow'}, ['CITEREFKasheff2001'] = template_names['Iranica'], ['CITEREFKayvaniGholami2008'] = {'Encyclopaedia Islamica'}, ['CITEREFKazhdan1991'] = template_names['ODB'], ['CITEREFKazhdanCutler1991'] = template_names['ODB'], ['CITEREFKazhdanJeffreys1991'] = template_names['ODB'], ['CITEREFKazhdanŠevčenko1991'] = template_names['ODB'], ['CITEREFKeall1987'] = template_names['Iranica'], ['CITEREFKeefe2006'] = {'Schubert\'s compositions (references)'}, ['CITEREFKeller1937'] = {'Bach\'s compositions (sources)'}, ['CITEREFKelly1988'] = {'Cite GEIL'}, ['CITEREFKellyBurrage1920'] = {'Cite AMB1920'}, ['CITEREFKennedy1998'] = {'The Cambridge History of Egypt', 'Cite Kennedy 1998', 'Cambridge History of Egypt'}, ['CITEREFKennedy2001'] = {'Kennedy-The Armies of the Caliphs'}, ['CITEREFKennedy2004'] = {'The Prophet and the Age of the Caliphates'}, ['CITEREFKennedy2007'] = {'Kennedy-The Great Arab Conquests'}, ['CITEREFKennedy2016'] = {'The Prophet and the Age of the Caliphates'}, ['CITEREFKenyon2011'] = {'Bach\'s compositions (sources)'}, ['CITEREFKerrigan1995'] = {'Shakespeare sonnets bibliography'}, ['CITEREFKettenhofen1995'] = template_names['Iranica'], ['CITEREFKettenhofen2001'] = template_names['Iranica'], ['CITEREFKettenhofenBournoutianHewsen1998'] = template_names['Iranica'], ['CITEREFKhaleelulla1982'] = {'Khaleelulla Counterexamples in Topological Vector Spaces'}, ['CITEREFKhaleghi-Motlagh1999'] = template_names['Iranica'], ['CITEREFKhaleghi-Motlagh2001'] = template_names['Iranica'], ['CITEREFKhan2012'] = {'Cite Banglapedia'}, ['CITEREFKhatibiNegahban2013'] = {'Encyclopaedia Islamica'}, ['CITEREFKim1994'] = {'Country study'}, ['CITEREFKirnberger1774'] = {'Bach\'s compositions (sources)'}, ['CITEREFKirnberger1780'] = {'Bach\'s compositions (sources)'}, ['CITEREFKlein2006'] = {'Klein-UP-2'}, ['CITEREFKlíma1988'] = template_names['Iranica'], ['CITEREFKobayashi1978'] = {'Bach\'s compositions (sources)'}, ['CITEREFKoderHild1976'] = {'Tabula Imperii Byzantini'}, ['CITEREFKoderSoustalKoder1998'] = {'Tabula Imperii Byzantini'}, ['CITEREFKoeppel2015'] = {'Cite citygrid'}, ['CITEREFKofos1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFKohler1902'] = {'Cite Jewish Encyclopedia'}, ['CITEREFKolde1914'] = {'Schaff-Herzog'}, ['CITEREFKoliopoulos1978'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFKolmogorovFomin1957'] = {'Kolmogorov Fomin Elements of the Theory of Functions and Functional Analysis'}, ['CITEREFKonrad_Ameln1985'] = template_names['NDB'], ['CITEREFKoska2011'] = {'Bach\'s compositions (sources)'}, ['CITEREFKratville1962'] = {'Kratville-SSL'}, ['CITEREFKretzschmar1910'] = {'Bach\'s compositions (sources)'}, ['CITEREFKube2009'] = {'Schubert\'s compositions (references)'}, ['CITEREFKurz1983'] = template_names['Cam_Hist_Iran'], ['CITEREFKuznik2008'] = {'Bach\'s compositions (sources)'}, ['CITEREFKöthe1969'] = {'Köthe Topological Vector Spaces I'}, ['CITEREFKöthe1979'] = {'Köthe Topological Vector Spaces II'}, ['CITEREFKöthe1983'] = {'Köthe Topological Vector Spaces I'}, ['CITEREFKülzer2008'] = {'Tabula Imperii Byzantini'}, ['CITEREFKüçükaşcı2001'] = {'TDV Encyclopedia of Islam'}, ----------< L >---------- ['CITEREFLa_Porta2018'] = template_names['ODLA'], ['CITEREFLacourcière1974'] = {'Cite DCB'}, ['CITEREFLadefogedMaddieson1996'] = {'SOWL'}, ['CITEREFLandau-Tasseron2010'] = {'New Cambridge History of Islam'}, ['CITEREFLandauCondit1996'] = {'Cite nysky'}, ['CITEREFLandmann1907'] = {'Bach\'s compositions (sources)'}, ['CITEREFLang1983'] = template_names['Cam_Hist_Iran'], ['CITEREFLangaroodiCooper2008'] = {'Encyclopaedia Islamica'}, ['CITEREFLangaroodiCooper2015'] = template_names['Iranica'], ['CITEREFLangaroodiCooper2015'] = {'Encyclopaedia Islamica'}, ['CITEREFLangaroodiNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFLangaroodiNegahban2015'] = template_names['Iranica'], ['CITEREFLangaroodiNegahban2015'] = {'Encyclopaedia Islamica'}, ['CITEREFLangaroudi2001'] = template_names['Iranica'], ['CITEREFLatham1982–2021'] = template_names['Iranica'], ['CITEREFLazard1975'] = template_names['Cam_Hist_Iran'], ['CITEREFLaërtius1925'] = {'Cite Lives of the Eminent Philosophers', 'Cite LotEP'}, ['CITEREFLeCoq1986'] = template_names['Iranica'], ['CITEREFLe_Quien1740'] = {'Oriens Christianus'}, ['CITEREFLe_Strange1900'] = {'Baghdad During the Abbasid Caliphate'}, ['CITEREFLe_Strange1905'] = {'Lands of the Eastern Caliphate'}, ['CITEREFLe_Strange1922'] = {'Baghdad During the Abbasid Caliphate'}, ['CITEREFLeblanc1979'] = {'Cite DCB'}, ['CITEREFLee1903'] = {'Cite DNBIE'}, ['CITEREFLee2018'] = template_names['ODLA'], ['CITEREFLeisingerWollny1993'] = {'Bach\'s compositions (sources)'}, ['CITEREFLerner1988'] = template_names['Iranica'], ['CITEREFLev1999'] = {'Saladin in Egypt'}, ['CITEREFLevitan2001'] = {'Springer'}, ['CITEREFLewin1925'] = {'Lewin-EarlyRail'}, ['CITEREFLewis1969'] = {'Setton-A History of the Crusades'}, ['CITEREFLewis1986'] = {'Lewis-Shortline-1986'}, ['CITEREFLewis1991'] = {'Lewis-Shortline-1991'}, ['CITEREFLewis1996'] = {'Lewis-Shortline-1996'}, ['CITEREFLewis2001'] = template_names['Iranica'], ['CITEREFLiederNet_Archive'] = {'Schubert\'s compositions (references)'}, ['CITEREFLieu1997'] = template_names['Iranica'], ['CITEREFLighthouses_of_Australia_Inc'] = {'Cite loa'}, ['CITEREFLind1986'] = {'Lind-Limiteds'}, ['CITEREFLittle1974'] = {'Cite DCB'}, ['CITEREFLongnon1969'] = {'Setton-A History of the Crusades'}, ['CITEREFLosensky2003'] = template_names['Iranica'], ['CITEREFLoverance2018'] = template_names['ODLA'], ['CITEREFLukonin1983'] = {'Cambridge History of Iran'}, ['CITEREFLurje2010'] = template_names['Iranica'], ['CITEREFLuttrell1975'] = {'Setton-A History of the Crusades'}, ['CITEREFLuttrell1987'] = {'DBI'}, ['CITEREFLynch2004'] = {'Lynch-Penn Central'}, ['CITEREFLynch2005'] = {'Lynch-New Haven passenger'}, ['CITEREFLynch2018'] = template_names['ODLA'], ['CITEREFLéger1990'] = {'Cite DCB'}, ['CITEREFle_Fleming1953'] = {'RCTS-LocosGWR-8'}, ['CITEREFle_Fleming1960'] = {'RCTS-LocosGWR-8'}, ----------< M >---------- ['CITEREFMacDermot1927'] = {'Infobox GWR'}, ['CITEREFMacDermot1931'] = {'Infobox GWR'}, ['CITEREFMacEoin1988'] = template_names['Iranica'], ['CITEREFMacKenzie1992'] = template_names['Iranica'], ['CITEREFMadelung1975'] = template_names['Cam_Hist_Iran'], ['CITEREFMadelung1978'] = {'EI2'}, ['CITEREFMadelung1983'] = template_names['Iranica'], ['CITEREFMadelung1984'] = template_names['Iranica'], ['CITEREFMadelung1988'] = template_names['Iranica'], ['CITEREFMadelung1993'] = template_names['Iranica'], ['CITEREFMadelung2003'] = template_names['Iranica'], ['CITEREFMadelungFelix1995'] = template_names['Iranica'], ['CITEREFMaeda2009'] = template_names['Iranica'], ['CITEREFMagdalino2002'] = {'The Empire of Manuel I Komnenos'}, ['CITEREFMaiken1989'] = {'Maiken-Night Trains'}, ['CITEREFMailer2004'] = {'Mailer-Omaha Road'}, ['CITEREFMajidiNegahban'] = {'Encyclopaedia Islamica'}, ['CITEREFMalandra2009'] = template_names['Iranica'], ['CITEREFManfred_Knedlik2007'] = {'BBKL'}, ['CITEREFMarshak1994'] = template_names['Iranica'], ['CITEREFMarshak2002'] = template_names['Iranica'], ['CITEREFMarshall1823'] = {'Cite RNB1823'}, ['CITEREFMarshall1824'] = {'Cite RNB1823'}, ['CITEREFMarshall1825'] = {'Cite RNB1823'}, ['CITEREFMarshall1827'] = {'Cite RNB1823'}, ['CITEREFMarshall1828'] = {'Cite RNB1823'}, ['CITEREFMarshall1829'] = {'Cite RNB1823'}, ['CITEREFMarshall1830'] = {'Cite RNB1823'}, ['CITEREFMarshall1831'] = {'Cite RNB1823'}, ['CITEREFMarshall1832'] = {'Cite RNB1823'}, ['CITEREFMarshall1833'] = {'Cite RNB1823'}, ['CITEREFMarshall1835'] = {'Cite RNB1823'}, ['CITEREFMarshall1972'] = {'Lancashire & Yorkshire Railway 3'}, ['CITEREFMarshall2001'] = {'Marshall-INGSR'}, ['CITEREFMartin_Persch1992'] = {'BBKL'}, ['CITEREFMartin_Persch1993'] = {'BBKL'}, ['CITEREFMartin_Persch1996'] = {'BBKL'}, ['CITEREFMartindale1980'] = {'Prosopography of the Later Roman Empire', 'PLRE'}, ['CITEREFMartindale1992'] = {'Prosopography of the Later Roman Empire', 'PLRE'}, ['CITEREFMartindaleJonesMorris1971'] = {'Prosopography of the Later Roman Empire', 'PLRE'}, ['CITEREFMasoud_Jalali-Moqaddam2015'] = {'Encyclopaedia Islamica'}, ['CITEREFMatini1987'] = template_names['Iranica'], ['CITEREFMatthee2008'] = template_names['Iranica'], ['CITEREFMatthee2015'] = template_names['Iranica'], ['CITEREFMaul2005'] = {'Bach\'s compositions (sources)'}, ['CITEREFMayGray2006'] = {'MayGray-WAGRPassCar'}, ['CITEREFMazzaoui2002'] = template_names['Iranica'], ['CITEREFMcArthurMcArthur2003'] = {'Cite ogn', 'Cite Oregon Geographic Names'}, ['CITEREFMcCaffrey1990'] = template_names['Iranica'], ['CITEREFMcCorduck2004'] = {'McCorduck 2004'}, ['CITEREFMcCurdyRogers1902'] = {'Cite Jewish Encyclopedia'}, ['CITEREFMcDonnell2015'] = {'McDonnell-Locomotives-2nd'}, ['CITEREFMcGhee2008'] = {'Cite McGhee 2008'}, ['CITEREFMeiningen1704'] = {'Bach\'s compositions (sources)'}, ['CITEREFMeints1992'] = {'Meints-Companies'}, ['CITEREFMeints2005'] = {'Meints-Lines'}, ['CITEREFMelamed1988'] = {'Bach\'s compositions (sources)'}, ['CITEREFMelamed1995'] = {'Bach\'s compositions (sources)'}, ['CITEREFMelville1997'] = template_names['Iranica'], ['CITEREFMelville2003'] = template_names['Iranica'], ['CITEREFMennell1892'] = {'Dictionary of Australasian Biography'}, ['CITEREFMetcalfe2009'] = {'The Muslims of Medieval Italy'}, ['CITEREFMiddleton1961'] = {'Middleton-Interurban'}, ['CITEREFMiddleton2001'] = {'Middleton-Electrified-2nd'}, ['CITEREFMiddleton2002'] = {'Middleton-PRR-Under-Wire'}, ['CITEREFMiddletonSmerkDiehl2007'] = {'Encyclopedia of North American Railroads'}, ['CITEREFMiles1975'] = template_names['Cam_Hist_Iran'], ['CITEREFMillar2011'] = {'NZR Steam Locomotive'}, ['CITEREFMiller'] = {'Encyclopaedia Islamica'}, ['CITEREFMiller1908'] = {'The Latins in the Levant', 'Latins in the Levant'}, ['CITEREFMiller1921'] = {'Essays on the Latin Orient'}, ['CITEREFMinnich2008'] = {'Country study'}, ['CITEREFMiramar_Ship_Index'] = {'Csr', 'Cite ship register'}, ['CITEREFMitchell1965'] = {'Mitchell TOC'}, ['CITEREFMittermeierKonstantHawkinsLouis2006'] = {'LoM2'}, ['CITEREFMittermeierLouisRichardsonSchwitzer2010'] = {'LoM3'}, ['CITEREFMittermeierTattersallKonstantMeyers1994'] = {'LoM1'}, ['CITEREFMoore1875'] = {'Cite CEM'}, ['CITEREFMorana1993'] = {'Bach\'s compositions (sources)'}, ['CITEREFMorony2009'] = template_names['Iranica'], ['CITEREFMoschonas1975'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFMottahedeh1975'] = template_names['Cam_Hist_Iran'], ['CITEREFMozartHaydnHaydn2008'] = {'Schubert\'s compositions (references)'}, ['CITEREFMunkres1974'] = {'Munkres Topology'}, ['CITEREFMunkres2000'] = {'Munkres Topology'}, ['CITEREFMurray2006'] = {'Murray-Illinois Central'}, ['CITEREFMusserCarleton2005'] = {'MSW3 Muroidea'}, ['CITEREFMüller,_Hans-Christian1966'] = template_names['NDB'], ----------< N >---------- ['CITEREFNSA_II,_15'] = {'Schubert\'s compositions (references)'}, ['CITEREFNSA_scores'] = {'Schubert\'s compositions (references)'}, ['CITEREFNSA_website'] = {'Schubert\'s compositions (references)'}, ['CITEREFNagel1990'] = template_names['Iranica'], ['CITEREFNariciBeckenstein2011'] = {'Narici Beckenstein Topological Vector Spaces'}, ['CITEREFNavāʾī1988'] = template_names['Iranica'], ['CITEREFNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFNersessian2018'] = template_names['ODLA'], ['CITEREFNetzer1998'] = template_names['Iranica'], ['CITEREFNetzer2007'] = template_names['Iranica'], ['CITEREFNeukirch1999'] = {'Neukirch ANT'}, ['CITEREFNeukirchSchmidtWingberg2000'] = {'Neukirch et al. CNF'}, ['CITEREFNew_York_City_Landmarks_Preservation_CommissionDolkartPostal2009'] = {'Cite nycland'}, ['CITEREFNewbould1999'] = {'Schubert\'s compositions (references)'}, ['CITEREFNewman1994'] = template_names['Iranica'], ['CITEREFNicholsonCanepaDaryaee2018'] = template_names['ODLA'], ['CITEREFNicol1988'] = {'Byzantium and Venice: A Study in Diplomatic and Cultural Relations'}, ['CITEREFNicol1992'] = {'The Immortal Emperor: The Life and Legend of Constantine Palaiologos, Last Emperor of the Romans'}, ['CITEREFNicol1993'] = {'The Last Centuries of Byzantium, 1261–1453', 'The Last Centuries of Byzantium'}, ['CITEREFNock1974'] = {'Nock-EustonGlasgow'}, ----------< O >---------- ['CITEREFO&#039;Byrne1849'] = {'Cite NBD1849'}, ['CITEREFO&#039;ConnorRobertson1996'] = {'MacTutor Biography', 'MacTutor'}, ['CITEREFO&#039;ConnorRobertson2000'] = {'MacTutor Biography', 'MacTutor'}, ['CITEREFO&#039;Donoghue1897'] = {'Cite DNB'}, ['CITEREFODB'] = template_names['ODB'], ['CITEREFODLA'] = template_names['ODLA'], ['CITEREFOberling1984'] = template_names['Iranica'], ['CITEREFOberling2008'] = template_names['Iranica'], ['CITEREFOberling2010'] = template_names['Iranica'], ['CITEREFOdisheli2018'] = template_names['ODLA'], ['CITEREFOfficial_Guide_of_the_Railways1950'] = {'Official Guide of the Railways'}, ['CITEREFOgorek2012'] = {'Ogorek-South Shore'}, ['CITEREFOikonomides1991'] = template_names['ODB'], ['CITEREFOikonomou1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFOlbrycht2021'] = template_names['Iranica'], ----------< P >---------- ['CITEREFPLP'] = {'Prosopographisches Lexikon der Palaiologenzeit', 'PLP'}, ['CITEREFPalmer1875'] = {'Cite ADB'}, ['CITEREFPalmerStewart1965'] = {'Palmer & Stewart'}, ['CITEREFPanainoAbdollahyBalland1990'] = template_names['Iranica'], ['CITEREFPandariHirtensteinNegahban2013'] = {'Encyclopaedia Islamica'}, ['CITEREFParvin2003'] = template_names['Iranica'], ['CITEREFParvin2009'] = template_names['Iranica'], ['CITEREFPatience1996'] = {'Patience-SteamTwilight'}, ['CITEREFPatton2005'] = {'MSW3 Geomyidae'}, ['CITEREFPaul2000'] = template_names['Iranica'], ['CITEREFPaxtonBourne1985'] = {'Paxton-Bourne'}, ['CITEREFPeacock2011'] = template_names['Iranica'], ['CITEREFPeck1898'] = {'HDCA'}, ['CITEREFPerlis2001'] = {'Springer'}, ['CITEREFPerreault2004'] = {'Bach\'s compositions (sources)'}, ['CITEREFPerry1983'] = template_names['Cam_Hist_Iran'], ['CITEREFPerry1990'] = template_names['Cam_Hist_Iran'], ['CITEREFPerry1991'] = template_names['Cam_Hist_Iran'], ['CITEREFPetropoulosKoumarianou1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFPetrucci1982'] = {'DBI'}, ['CITEREFPezeshk2017'] = {'Encyclopaedia Islamica'}, ['CITEREFPezeshkKhaleeli2017'] = template_names['Iranica'], ['CITEREFPezeshkKhaleeli2017'] = {'Encyclopaedia Islamica'}, ['CITEREFPfau2008'] = {'Bach\'s compositions (sources)'}, ['CITEREFPinkepank1973'] = {'Pinkepank diesel spotters guide 2'}, ['CITEREFPlantlist2016'] = {'Plantlist'}, ['CITEREFPlaten1976'] = {'Bach\'s compositions (sources)'}, ['CITEREFPloumidisAlexiou1974'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFPmbZ'] = {'Prosopographie der mittelbyzantinischen Zeit', 'PMBZ'}, ['CITEREFPolemis1968'] = {'Polemis-The Doukai'}, ['CITEREFPope2007'] = {'Encyclopaedia Judaica', 'Cite EJ', 'Cite Encyclopaedia Judaica'}, ['CITEREFPopplewell'] = {'Popplewell-Gazetteer'}, ['CITEREFPotts2018'] = template_names['ODLA'], ['CITEREFPottsCanepa2018'] = template_names['ODLA'], ['CITEREFPourshariati2017'] = {'Encyclopædia Iranica Online'}, ['CITEREFPozza1992'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFPrawer1985'] = {'Setton-A History of the Crusades'}, ['CITEREFPritsak1991'] = template_names['ODB'], ['CITEREFProsopographie_der_mittelbyz._Zeit'] = {'Prosopographie der mittelbyzantinischen Zeit'}, ----------< Q >---------- ['CITEREFQuick2009'] = {'Quick-Stations'}, ['CITEREFQuick2019'] = {'Quick-stations-5'}, ['CITEREFQuinn2003'] = template_names['Iranica'], ----------< R >---------- ['CITEREFRaditsa1983'] = template_names['Cam_Hist_Iran'], ['CITEREFRahman1983'] = template_names['Iranica'], ['CITEREFRaja&#039;i1987'] = template_names['Iranica'], ['CITEREFRamaer1974'] = {'Ramaer-SteamLocosEAR'}, ['CITEREFRansome-Wallis1971'] = {'Ransome-Wallis 1'}, ['CITEREFRateliff2007'] = template_names['ME-ref'], ['CITEREFRavegnano2000'] = {'DBI'}, ['CITEREFReed1953'] = {'RCTS-LocosGWR-2'}, ['CITEREFReed1975'] = {'Reed-Streamline era'}, ['CITEREFReed1997'] = {'Schubert\'s compositions (references)'}, ['CITEREFReinhard_Tenberg1990'] = {'BBKL'}, ['CITEREFRettinghaus2020'] = {'BDh'}, ['CITEREFReynolds1921'] = {'Cite Collier\'s', 'Collier\'s'}, ['CITEREFReynoldsOroszi2000'] = {'Reynolds-BO'}, ['CITEREFRezaHirtensteinGholami2021'] = {'Encyclopaedia Islamica'}, ['CITEREFRezakhani2018'] = template_names['ODLA'], ['CITEREFRezvani2014'] = template_names['Iranica'], ['CITEREFRichter-Bernburg2003'] = template_names['Iranica'], ['CITEREFRichter2018'] = {'BDh'}, ['CITEREFRigo2005'] = template_names['ODB'], ['CITEREFRipleyDana1863'] = {'New American Cyclopedia'}, ['CITEREFRipleyDana1864'] = {'New American Cyclopedia'}, ['CITEREFRipleyDana1879'] = {'Cite AmCyc'}, ['CITEREFRistaino1988'] = {'Country study'}, ['CITEREFRobert_Eitner1891'] = {'Cite ADB'}, ['CITEREFRobertson1983'] = {'Robertson-OriginScot'}, ['CITEREFRoe1916'] = {'Roe1916'}, ['CITEREFRoe1937'] = {'Roe1937'}, ['CITEREFRoemer1986'] = template_names['Cam_Hist_Iran'], ['CITEREFRoemer1989'] = template_names['Iranica'], ['CITEREFRoemer2004'] = template_names['Iranica'], ['CITEREFRolt1965'] = {'Rolt1965'}, ['CITEREFRoltKichenside1982'] = {'Rolt-Red'}, ['CITEREFRose1857'] = {'Cite Newgenbio'}, ['CITEREFRosenfeld1974'] = template_names['NDB'], ['CITEREFRosenzweigBlackmar1992'] = {'Cite Central Park History', 'Cite Central Park history'}, ['CITEREFRowledge1975'] = {'Rowledge-Engines of the LMS'}, ['CITEREFRowledge1993'] = {'Rowledge-Irish Steam Register'}, ['CITEREFRowlett'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2007'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2012'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2013'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2016'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2017'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowson1998'] = template_names['Iranica'], ['CITEREFRudin1973'] = {'Rudin Walter Functional Analysis'}, ['CITEREFRudin1991'] = {'Rudin Walter Functional Analysis'}, ['CITEREFRunciman1951'] = {'Runciman-A History of the Crusades'}, ['CITEREFRunciman1951–1954'] = {'Runciman-A History of the Crusades'}, ['CITEREFRunciman1952'] = {'Runciman-A History of the Crusades'}, ['CITEREFRunciman1954'] = {'Runciman-A History of the Crusades'}, ['CITEREFRunciman1989'] = {'Runciman-A History of the Crusades'}, ['CITEREFRussell1985'] = {'Setton-A History of the Crusades', 'Encyclopædia Iranica Online', 'Encyclopædia Iranica', 'Encyclopaedia Iranica', 'Cite Encyclopædia Iranica Online'}, ['CITEREFRussell1986'] = template_names['Iranica'], ['CITEREFRussell1987'] = template_names['Iranica'], ['CITEREFRussellNorvig2003'] = {'Russell Norvig 2003'}, ['CITEREFRybczynski2000'] = {'Rybczynski2000'}, ['CITEREFRypka1968'] = template_names['Cam_Hist_Iran'], ----------< S >---------- ['CITEREFSR_staff2013'] = {'Houston family tree'}, ['CITEREFSadeghiTehrani2008'] = {'Encyclopaedia Islamica'}, ['CITEREFSadıkoğlu1996'] = {'TDV Encyclopedia of Islam'}, ['CITEREFSafa1987'] = template_names['Iranica'], ['CITEREFSafa1988'] = template_names['Iranica'], ['CITEREFSafa1989'] = template_names['Iranica'], ['CITEREFSafa1994'] = template_names['Iranica'], ['CITEREFSafa2003'] = template_names['Iranica'], ['CITEREFSajjadiAsatryanMelvin-Koushki'] = {'Encyclopaedia Islamica Online'}, ['CITEREFSajjadiAsatryanMelvin-Koushki'] = {'Encyclopaedia Islamica'}, ['CITEREFSajjadiAsatryanMelvin-Koushki2021'] = template_names['Iranica'], ['CITEREFSalbiev2021'] = template_names['Iranica'], ['CITEREFSalo2004'] = template_names['ME-ref'], ['CITEREFSamiʿiMelvin-Koushki2013'] = {'Encyclopaedia Islamica'}, ['CITEREFSanders1998'] = {'The Cambridge History of Egypt', 'Cambridge History of Egypt'}, ['CITEREFSanders2003'] = {'Sanders-Indiana'}, ['CITEREFSanders2006'] = {'Sanders-Heartland'}, ['CITEREFSanders2007'] = {'Sanders-Akron'}, ['CITEREFSarikakis1974'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFSaunders2001'] = {'Saunders-Merging Lines'}, ['CITEREFSaunders2013'] = {'Saunders-Giants of the Seas'}, ['CITEREFSavadaShaw1992'] = {'Country study'}, ['CITEREFSavoryKaramustafa1998'] = template_names['Iranica'], ['CITEREFScarce1986'] = template_names['Iranica'], ['CITEREFSchaeferWolff1999'] = {'Schaefer Wolff Topological Vector Spaces'}, ['CITEREFSchafer1996'] = {'Schafer-Classic-Railroads-1'}, ['CITEREFSchafer1998'] = {'Schafer-Vintage Diesel'}, ['CITEREFSchafer2000'] = {'Schafer-More-Classic'}, ['CITEREFSchafer2003'] = {'Schafer-Classic-Railroads-3'}, ['CITEREFSchaferSolomon1997'] = {'Schafer-Pennsylvania'}, ['CITEREFSchaferWelsh1997'] = {'Schafer-Classic'}, ['CITEREFSchaferWelsh2002'] = {'Schafer-Streamliners'}, ['CITEREFSchaferWelshHolland2001'] = {'Schafer-American passenger train'}, ['CITEREFSchaff-Herzog'] = {'Schaff-Herzog'}, ['CITEREFSchechter1996'] = {'Schechter Handbook of Analysis and Its Foundations'}, ['CITEREFScheide1960'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchicht1805'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchilling1997'] = {'Schilling-pop-culture'}, ['CITEREFSchindel2013'] = template_names['Iranica'], ['CITEREFSchippmann1986'] = template_names['Iranica'], ['CITEREFSchippmann1987'] = template_names['Iranica'], ['CITEREFSchlitter2005'] = {'MSW3 Tubulidentata'}, ['CITEREFSchlumberger1983'] = template_names['Cam_Hist_Iran'], ['CITEREFSchmieder1950'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchmieder1990'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchmitt1986'] = template_names['Iranica'], ['CITEREFSchmitt1989'] = template_names['Iranica'], ['CITEREFSchmitt1993'] = template_names['Iranica'], ['CITEREFSchmitt1994'] = template_names['Iranica'], ['CITEREFSchmitt1995'] = template_names['Iranica'], ['CITEREFSchmitt2002'] = template_names['Iranica'], ['CITEREFSchmitt2004'] = template_names['Iranica'], ['CITEREFSchmitt2005'] = template_names['Iranica'], ['CITEREFSchmitt2018'] = template_names['Iranica'], ['CITEREFSchmittBailey1986'] = template_names['Iranica'], ['CITEREFSchmitz1870'] = {'Cite DGRBM'}, ['CITEREFSchneider1907'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchneider1912'] = {'Bach\'s compositions (sources)'}, ['CITEREFScholze1736'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchroeter1961'] = {'Schroeter-Eisenbahnen'}, ['CITEREFSchroeterRamaer1993'] = {'Schroeter-Ramaer-Eisenbahnen'}, ['CITEREFSchubert-online'] = {'Schubert\'s compositions (references)'}, ['CITEREFSchubert1968'] = {'Schubert Topology'}, ['CITEREFSchulenberg2010'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchulenberg2013'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchulze1980'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchulze1983'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchulze1984'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchwieterman2001'] = {'Schwieterman-Leaves-Eastern'}, ['CITEREFScottNegus2011'] = {'Scott-Negus-Cellar Door'}, ['CITEREFScribbins1970'] = {'Scribbins-Hiawatha'}, ['CITEREFScribbins2008'] = {'Scribbins-400-2008', 'Scribbins-Remembered'}, ['CITEREFSearle'] = {'Cite sslidx'}, ['CITEREFSegal1982'] = template_names['Iranica'], ['CITEREFSellwood1983'] = template_names['Cam_Hist_Iran'], ['CITEREFSemmensGoldfinch2000'] = {'Book-Semmens-Goldfinch-How Steam Locomotives Really Work'}, ['CITEREFSemsarZand2008'] = {'Encyclopaedia Islamica'}, ['CITEREFSetton1975'] = {'Setton-A History of the Crusades'}, ['CITEREFSetton1976'] = {'The Papacy and the Levant'}, ['CITEREFSetton1978'] = {'The Papacy and the Levant'}, ['CITEREFSetton1984'] = {'The Papacy and the Levant'}, ['CITEREFSettonHazard1975'] = {'Setton-A History of the Crusades'}, ['CITEREFSfyroeras1975'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFShahbazi1986'] = template_names['Iranica'], ['CITEREFShahbazi1987'] = template_names['Iranica'], ['CITEREFShahbazi1988'] = template_names['Iranica'], ['CITEREFShahbazi1989'] = template_names['Iranica'], ['CITEREFShahbazi1991'] = template_names['Iranica'], ['CITEREFShahbazi1994'] = template_names['Iranica'], ['CITEREFShahbazi2002'] = template_names['Iranica'], ['CITEREFShahbazi2003'] = template_names['Iranica'], ['CITEREFShahbazi2004'] = template_names['Iranica'], ['CITEREFShahbazi2005'] = template_names['Iranica'], ['CITEREFShahbaziBosworth1990'] = template_names['Iranica'], ['CITEREFShahbaziRichter-Bernburg2002'] = template_names['Iranica'], ['CITEREFShaki1991'] = template_names['Iranica'], ['CITEREFShaughnessy1997'] = {'Shaughnessy-DH'}, ['CITEREFShaw1978'] = {'Shaw-RailroadAccidents'}, ['CITEREFShayegan2004'] = template_names['Iranica'], ['CITEREFShayesteh2013'] = template_names['Iranica'], ['CITEREFSheikhsofla2018'] = {'Encyclopaedia Islamica'}, ['CITEREFShindo2004'] = {'Kaneto-shindo-shinario-jinsei'}, ['CITEREFShoarian-SattariRezaeeNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFShoshani2005'] = {'MSW3 Shoshani'}, ['CITEREFShtern2001'] = {'Springer', 'SpringerEOM'}, ['CITEREFSiegele1957'] = {'Bach\'s compositions (sources)'}, ['CITEREFSilanos2014'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFSilke2006'] = {'O\'Donnell family tree'}, ['CITEREFSimmons2005'] = {'MSW3 Chiroptera'}, ['CITEREFSimon1966'] = {'Simon-Wines Australia'}, ['CITEREFSimonWarner2011'] = {'Amtrak By the Numbers'}, ['CITEREFSinclair1911'] = {'DCBL'}, ['CITEREFSinger1905'] = {'Jewish Encyclopedia'}, ['CITEREFSix1934'] = {'Cite Six', 'Cite six'}, ['CITEREFSkjærvø2018'] = template_names['ODLA'], ['CITEREFSkoulatos1980'] = {'Les personnages byzantins de l\'Alexiade'}, ['CITEREFSloan1964'] = {'Sloan1964'}, ['CITEREFSmith1854'] = {'Cite DGRG', 'DGRG'}, ['CITEREFSmith1870'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFSmith1873'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFSmith1876'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFSmith1880'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFSmith2010'] = {'Smith-Cruise Ships-2010'}, ['CITEREFSolomentsev2001'] = {'Springer', 'SpringerEOM'}, ['CITEREFSolomon2000'] = {'Solomon-American Diesel', 'Solomon-UP'}, ['CITEREFSolomon2003'] = {'Solomon-Masterpieces'}, ['CITEREFSolomon2004'] = {'Solomon-Amtrak'}, ['CITEREFSolomon2005'] = {'Solomon-SP-Passenger'}, ['CITEREFSolomon2006'] = {'Solomon-EMD Locomotives'}, ['CITEREFSolomon2011'] = {'Solomon-Modern Diesel'}, ['CITEREFSolomon2014'] = {'Solomon-GE and EMD'}, ['CITEREFSolomonSchafer2007'] = {'Solomon-New York Central'}, ['CITEREFSolopova2009'] = template_names['ME-ref'], ['CITEREFSoucek1982'] = template_names['Iranica'], ['CITEREFSoucek1983'] = template_names['Iranica'], ['CITEREFSoustal1991'] = {'Tabula Imperii Byzantini'}, ['CITEREFSoustalKoder1981'] = {'Tabula Imperii Byzantini'}, ['CITEREFSpielhoff1991'] = {'Spielhoff-EL'}, ['CITEREFSpitta1894'] = {'Bach\'s compositions (sources)'}, ['CITEREFSpitta1899'] = {'Bach\'s compositions (sources)'}, ['CITEREFSpringirth2016'] = {'Springirth-Philadelphia'}, ['CITEREFSpuhler1986'] = template_names['Cam_Hist_Iran'], ['CITEREFSpuler1983'] = template_names['Iranica'], ['CITEREFSpuler1987'] = template_names['Iranica'], ['CITEREFStagner1993'] = {'Stagner-Transition'}, ['CITEREFStansfield1999'] = {'Stansfield-AyrRenfrew'}, ['CITEREFStatistical_Yearbook_of_the_Republic_of_Croatia_2015'] = {'Croatia Yearbook 2015'}, ['CITEREFStaufer1993'] = {'Staufer-Pennsy_III'}, ['CITEREFStauferPennypacker1962'] = {'Staufer-Pennsy'}, ['CITEREFStauferPennypacker1968'] = {'Staufer-Pennsy Power II'}, ['CITEREFStaunton1988'] = {'Australian Dictionary of Biography'}, ['CITEREFSternFishmanTilove2006'] = {'Cite New York 2000', 'Cite NY2000', 'Cite ny2000', 'Cite NY 2000', 'Cite ny 2000'}, ['CITEREFSternGilmartinMassengale1983'] = {'Cite New York 1900', 'Cite NY1900'}, ['CITEREFSternGilmartinMellins1987'] = {'Cite New York 1930', 'Cite NY 1930', 'Cite NY1930', 'Cite ny1930', 'Cite ny 1930'}, ['CITEREFSternMellinsFishman1995'] = {'Cite New York 1960', 'Cite NY1960', 'Cite NY 1960', 'Cite ny1960', 'Cite ny 1960'}, ['CITEREFSternMellinsFishman1999'] = {'Cite New York 1880', 'Cite NY1880', 'Cite NY 1880', 'Cite ny1880', 'Cite ny 1880'}, ['CITEREFStewart1974'] = {'When Steam Was King'}, ['CITEREFStrachey1981'] = template_names['ME-ref'], ['CITEREFStrickland1983'] = {'Strickland Locomotive Directory'}, ['CITEREFStähelin1909'] = {'Schaff-Herzog'}, ['CITEREFSuetin2001'] = {'Springer', 'SpringerEOM'}, ['CITEREFSundermann1988'] = template_names['Iranica'], ['CITEREFSusanne_Schurr1992'] = {'BBKL'}, ['CITEREFSusanne_Siebert1992'] = {'BBKL'}, ['CITEREFSvolopoulos1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFSwartz1992'] = {'Swartz An Introduction to Functional Analysis'}, ----------< T >---------- ['CITEREFLondon_Gazette'] = {'London Gazette'}, ['CITEREFTaber1977'] = {'Taber-DLW-19th'}, ['CITEREFTaberTaber1980'] = {'Taber-DLW-20th-1'}, ['CITEREFTaberTaber1981'] = {'Taber-DLW-20th-2'}, ['CITEREFTafazzoli1999'] = template_names['Iranica'], ['CITEREFTafazzoli1999'] = {'Encyclopaedia Islamica'}, ['CITEREFTafazzoli2000'] = template_names['Iranica'], ['CITEREFTalbot1991'] = template_names['ODB'], ['CITEREFTalbotKazhdan1991'] = template_names['ODB'], ['CITEREFTanındı2008'] = template_names['Iranica'], ['CITEREFTao2009'] = {'Cite Cambridge History of China'}, ['CITEREFTer-Ghewondyan1976'] = {'The Arab Emirates in Bagratid Armenia'}, ['CITEREFThe_London_Gazette1950'] = {'London Gazette'}, ['CITEREFThe_London_Gazette_26_September_1919'] = {'London Gazette'}, ['CITEREFThielemann2012'] = {'Bach\'s compositions (sources)'}, ['CITEREFThomas1970'] = {'HistoryofParliament'}, ['CITEREFThomas1971'] = {'Thomas-History-VI'}, ['CITEREFThrush2010'] = {'HistoryofParliament'}, ['CITEREFTikhomirov2001'] = {'Springer'}, ['CITEREFTittel1966'] = {'Bach\'s compositions (sources)'}, ['CITEREFTodt1996'] = {'BBKL'}, ['CITEREFTodtVest2014'] = {'Tabula Imperii Byzantini'}, ['CITEREFTolkien1937'] = template_names['ME-ref'], ['CITEREFTolkien1954'] = template_names['ME-ref'], ['CITEREFTolkien1955'] = template_names['ME-ref'], ['CITEREFTolkien1964'] = template_names['ME-ref'], ['CITEREFTolkien1966'] = template_names['ME-ref'], ['CITEREFTolkien1977'] = template_names['ME-ref'], ['CITEREFTolkien1980'] = template_names['ME-ref'], ['CITEREFTolkien1982'] = template_names['ME-ref'], ['CITEREFTolkien1983'] = template_names['ME-ref'], ['CITEREFTolkien1984'] = template_names['ME-ref'], ['CITEREFTolkien1985'] = template_names['ME-ref'], ['CITEREFTolkien1986'] = template_names['ME-ref'], ['CITEREFTolkien1987'] = template_names['ME-ref'], ['CITEREFTolkien1988'] = template_names['ME-ref'], ['CITEREFTolkien1989'] = template_names['ME-ref'], ['CITEREFTolkien1990'] = template_names['ME-ref'], ['CITEREFTolkien1992'] = template_names['ME-ref'], ['CITEREFTolkien1993'] = template_names['ME-ref'], ['CITEREFTolkien1994'] = template_names['ME-ref'], ['CITEREFTolkien1996'] = template_names['ME-ref'], ['CITEREFTolkien1998'] = template_names['ME-ref'], ['CITEREFTolkien1999'] = template_names['ME-ref'], ['CITEREFTolkien2007'] = template_names['ME-ref'], ['CITEREFTolkienSwan1978'] = template_names['ME-ref'], ['CITEREFTolkienTolkien1992'] = template_names['ME-ref'], ['CITEREFTonks1988'] = {'Tonks ironstone'}, ['CITEREFTonks1989'] = {'Tonks ironstone'}, ['CITEREFTonks1992'] = {'Tonks ironstone'}, ['CITEREFTopping1975'] = {'Setton-A History of the Crusades'}, ['CITEREFTorri2013'] = {'Bach\'s compositions (sources)'}, ['CITEREFTougher2018'] = template_names['ODLA'], ['CITEREFToumanoff1986'] = template_names['Iranica'], ['CITEREFToumanoff2010'] = template_names['Iranica'], ['CITEREFToumanoffChaumont1987'] = template_names['Iranica'], ['CITEREFTourret1995'] = {'Tourret-Allied Military Locomotives'}, ['CITEREFTrapp1991'] = template_names['ODB'], ['CITEREFTrappBeyerSturm-Schnabl1983'] = {'Prosopographisches Lexikon der Palaiologenzeit'}, ['CITEREFTrappWaltherBeyer1976'] = {'Prosopographisches Lexikon der Palaiologenzeit'}, ['CITEREFTrappWaltherBeyerSturm-Schnabl1978'] = {'Prosopographisches Lexikon der Palaiologenzeit'}, ['CITEREFTreadgold1988'] = {'The Byzantine Revival, 780–842'}, ['CITEREFTreadgold1997'] = {'A History of the Byzantine State and Society'}, ['CITEREFTrèves2006'] = {'Trèves François Topological vector spaces, distributions and kernels'}, ['CITEREFTucker2009'] = {'Encyclopaedia Islamica'}, ['CITEREFTurim1998'] = {'Turim-oshima'}, ['CITEREFTuring1950'] = {'Turing 1950'}, ----------< U >---------- ['CITEREFUS-NHub_Music_Deposit_31_(Klavierbüchlein_für_W._F._Bach)_at_Bach_Digital'] = {'Bach\'s compositions (sources)'}, ['CITEREFUtas2002'] = template_names['Iranica'], ['CITEREFUwe_Eckardt2001'] = {'BBKL'}, ['CITEREFunknown_author1881'] = {'Cite ADB'}, ['CITEREFunknown_author1882'] = {'Cite ADB'}, ----------< V >---------- ['CITEREFVakalopoulos1975'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFVan_Cleve1969'] = {'Setton-A History of the Crusades'}, ['CITEREFVan_Hoorickx1971'] = {'Schubert\'s compositions (references)'}, ['CITEREFVan_Hoorickx_1974–1976'] = {'Schubert\'s compositions (references)'}, ['CITEREFVan_Lint2018'] = template_names['ODLA'], ['CITEREFVan_Riemsdijk,_Compound_Locomotives'] = {'Book-Van Riemsdijk-Compound Locomotives'}, ['CITEREFVan_Tricht2011'] = {'The Latin Renovatio of Byzantium'}, ['CITEREFVandenberghen1989'] = {'Vandenberghen-SNCB12.2'}, ['CITEREFVarzos1984'] = {'Η Γενεαλογία των Κομνηνών', 'Varzos-Genealogy of the Komnenoi'}, ['CITEREFVasiliev1935'] = {'Byzance et les Arabes'}, ['CITEREFVasiliev1968'] = {'Byzance et les Arabes'}, ['CITEREFVendler1997'] = {'Shakespeare sonnets bibliography'}, ['CITEREFVenetis2012'] = template_names['Iranica'], ['CITEREFVenn1954'] = {'VennAC'}, ['CITEREFVesel1999'] = template_names['Iranica'], ['CITEREFVetter1713'] = {'Bach\'s compositions (sources)'}, ['CITEREFVevainaCanepa2018'] = template_names['ODLA'], ['CITEREFVeysey1958'] = {'Veysey-PE-1958'}, ['CITEREFVischer1912'] = {'Schaff-Herzog'}, ['CITEREFVogelsang2003'] = template_names['Iranica'], ['CITEREFVolkmer1991'] = {'Volkmer-Pennsy-Electric'}, ['CITEREFvan_Leyden1956'] = {'Bach\'s compositions (sources)'}, ['CITEREFvan_Lint2018'] = template_names['ODLA'], ['CITEREFvon_Prantl1879'] = {'Cite ADB'}, ----------< W >---------- ['CITEREFWagnerBäzoldZschechLüderitz1990'] = {'Wagner-EFA2.3.2'}, ['CITEREFWalter_Asmus1966'] = template_names['NDB'], ['CITEREFWayner1972'] = {'Wayner - Car names, numbers, consists'}, ['CITEREFWayner1973'] = {'Wayner-Spotter-2nd'}, ['CITEREFWebb2018'] = template_names['ODLA'], ['CITEREFWeber2016'] = template_names['Iranica'], ['CITEREFWechsler1979'] = {'Cite Cambridge History of China'}, ['CITEREFWegman2008'] = {'Wegman-Illustrated'}, ['CITEREFWeibel1994'] = {'Weibel IHA'}, ['CITEREFWeinrebHibbertKeayKeay2008'] = {'London encyclopedia'}, ['CITEREFWeisbrod1991'] = {'Weisbrod-EFA1.5'}, ['CITEREFWeisbrodMüllerPetznik1978'] = {'Weisbrod-EFA1.2'}, ['CITEREFWeiskopf1987'] = template_names['Iranica'], ['CITEREFWeiskopf1989'] = template_names['Iranica'], ['CITEREFWeiskopf1990'] = template_names['Iranica'], ['CITEREFWeiskopf1993'] = template_names['Iranica'], ['CITEREFWellhausen1927'] = {'The Arab Kingdom and its Fall'}, ['CITEREFWells1982'] = {'Accents of English'}, ['CITEREFWells2008'] = {'Cite LPD'}, ['CITEREFWelsh2006'] = {'Welsh-Broadway'}, ['CITEREFWelsh2008'] = {'Welsh-UP'}, ['CITEREFWerner_Raupp2001'] = {'BBKL'}, ['CITEREFWestcott1911'] = {'DCBL'}, ['CITEREFWestermayer,_Georg1882'] = {'Cite ADB'}, ['CITEREFWham1997'] = {'Wham-Ayrshire'}, ['CITEREFWharton1991'] = template_names['ODB'], ['CITEREFWhishaw1842'] = {'Whishaw-RailofGB-2ndEd'}, ['CITEREFWhishaw1969'] = {'Whishaw-RailofGB'}, ['CITEREFWhite1985'] = {'White-Passenger-1985'}, ['CITEREFWhite1993'] = {'White - American railroad freight car'}, ['CITEREFWhiteWillenskyLeadon2010'] = {'Cite aia5'}, ['CITEREFWhitehurst1973'] = {'Whitehurst GW Engines from 1940'}, ['CITEREFWhittow1996'] = {'The Making of Byzantium, 600–1025'}, ['CITEREFWickman1982'] = {'Country study'}, ['CITEREFWiesehöfer1986'] = template_names['Iranica'], ['CITEREFWiesehöfer2018'] = template_names['ODLA'], ['CITEREFWilansky2013'] = {'Wilansky Modern Methods in Topological Vector Spaces'}, ['CITEREFWillard2004'] = {'Willard General Topology'}, ['CITEREFWilliams1998'] = {'Williams-Philadelphia'}, ['CITEREFWilliams2003'] = {'Bach\'s compositions (sources)'}, ['CITEREFWilliams2014'] = template_names['Iranica'], ['CITEREFWillis1750'] = {'Cite Notitia Parliamentaria'}, ['CITEREFWilson2017'] = {'Wilson-Guide'}, ['CITEREFWilsonFiske1891'] = {'Appletons\'', 'Cite Appletons\'', 'Appletons'}, ['CITEREFWilsonFiske1892'] = {'Appletons\'', 'Cite Appletons\'', 'Appletons'}, ['CITEREFWilsonFiske1900'] = {'Appletons\'', 'Cite Appletons\'', 'Appletons'}, ['CITEREFWiltshire2000'] = {'Lloyd-Margaret River'}, ['CITEREFWinfieldLyon2004'] = {'Winfield'}, ['CITEREFWinkler1883'] = template_names['ADB'], ['CITEREFWitakowski2018'] = template_names['ODLA'], ['CITEREFWolff1969'] = {'Setton-A History of the Crusades'}, ['CITEREFWollny2015'] = {'Bach\'s compositions (sources)'}, ['CITEREFWood1907'] = {'Cite Nuttall', 'Nuttall'}, ['CITEREFWoodsKilpatrick2005'] = {'MSW3 Hystricognathi'}, ['CITEREFWorden2008'] = {'Country study'}, ['CITEREFWortley2010'] = {'John Skylitzes: A Synopsis of Byzantine History, 811–1057'}, ['CITEREFWozencraft2005'] = {'MSW3 Carnivora'}, ['CITEREFWright1979'] = {'Cite Cambridge History of China'}, ['CITEREFWright2000'] = {'Bach\'s compositions (sources)'}, ['CITEREFWägliJacobi2010'] = {'Schienennetz Schweiz'}, ['CITEREFWürsch2013'] = template_names['Iranica'], ----------< X >---------- ----------< Y >---------- ['CITEREFYakubova2016'] = template_names['Iranica'], ['CITEREFYarshater1983'] = template_names['Iranica'], ['CITEREFYarshater1986'] = template_names['Cam_Hist_Iran'], ['CITEREFYarshater1988'] = template_names['Iranica'], ['CITEREFYarshater2018'] = template_names['Iranica'], ['CITEREFYarshater2021'] = template_names['Iranica'], ['CITEREFYazici2002'] = template_names['Iranica'], ['CITEREFYenne2005'] = {'Yenne-Chiefs'}, ['CITEREFYildiz2004'] = template_names['Iranica'], ['CITEREFYonge1990'] = {'Quail-4'}, ['CITEREFYonge1994'] = {'Quail-5'}, ['CITEREFYonge2002'] = {'Quail-5'}, ['CITEREFYonge2008'] = {'Quail-5'}, ['CITEREFYonge2016'] = {'Quail-2-2016'}, ['CITEREFYongePadgettSzwenk2013'] = {'Quail-4-Paper-3rdEd'}, ['CITEREFYusofi1990'] = template_names['Iranica'], ----------< Z >---------- ['CITEREFZahn1889–1893'] = {'Bach\'s compositions (sources)'}, ['CITEREFZakeri2021'] = template_names['Iranica'], ['CITEREFZarrinkoubNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFZarrinkub1975'] = template_names['Cam_Hist_Iran'], ['CITEREFZeiniWiesehöfer2018'] = template_names['ODLA'], ['CITEREFZekulich2000'] = {'Zekulich-WineWA'}, ['CITEREFZimmermann2004'] = {'Zimmermann-Burlington'}, ['CITEREFZimmermann2007'] = {'Zimmermann-GrandLuxe'}, ['CITEREFZuccaric._1747'] = {'Bach\'s compositions (sources)'}, ----------< UNSORTED >---------- ['CITEREFGazette27462'] = {'London Gazette'}, ['CITEREFCawley2012'] = {'Medieval Lands by Charles Cawley'}, ['CITEREFCrone2003'] = {'Slaves on Horses'}, ['CITEREFΙστορία_του_Ελληνικού_Έθνους'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFSpyropoulos1928'] = {'Great Military and Naval Encyclopaedia'}, ['CITEREFPikros1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFÖz1993'] = {'TDV Encyclopedia of Islam'}, ['CITEREFÖzgüdenli2008'] = template_names['Iranica'], ['CITEREFÖzaydın2002'] = {'TDV Encyclopedia of Islam'}, ['CITEREFÖzaydın2006'] = {'TDV Encyclopedia of Islam'}, ['CITEREFÖzkuyumcu2006'] = {'TDV Encyclopedia of Islam'}, ['CITEREFÖztürk2013'] = {'TDV Encyclopedia of Islam'}, ['CITEREFΜεγάλη_Στρατιωτικὴ_καὶ_Ναυτικὴ_Ἐγκυκλοπαιδεία'] = {'Great Military and Naval Encyclopaedia'}, ['CITEREFŞeşen1988'] = {'TDV Encyclopedia of Islam'}, ['CITEREFFranke1994'] = {'Cite Cambridge History of China', 'The Cambridge History of China'}, ['CITEREFTao2009'] = {'Cite Cambridge History of China', 'The Cambridge History of China'}, ['CITEREFWechsler1979'] = {'Cite Cambridge History of China', 'The Cambridge History of China'}, ['CITEREFWright1979'] = {'Cite Cambridge History of China', 'The Cambridge History of China'}, ['CITEREFHistoric_England_Benty_Grange'] = {'NHLE'}, ['CITEREFWalter1967'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFAliprantisBorder2006'] = {'Aliprantis Border Infinite Dimensional Analysis A Hitchhiker\'s Guide Third Edition'}, ['CITEREFAmanat1985'] = template_names['Iranica'], ['CITEREFBaldwin1991'] = template_names['ODB'], ['CITEREFCallwell1999'] = {'Muni Chronology'}, ['CITEREFHalmos1982'] = {'Halmos A Hilbert Space Problem Book 1982'}, ['CITEREFHistoric_England'] = {'NHLE', 'National Heritage List for England'}, ['CITEREFHitchins2001'] = template_names['Iranica'], ['CITEREFJohnson1906'] = {'BDA1906', 'Cite BDA1906'}, ['CITEREFMachinery&#039;s_Handbook1996'] = {'MachinerysHandbook25e'}, ['CITEREFMatthee2012'] = template_names['Iranica'], ['CITEREFNicholson2018'] = template_names['ODLA'], ['CITEREFNicol1968'] = {'The Byzantine Family of Kantakouzenos'}, ['CITEREFWilsonFiske1889'] = {'Appletons\'', 'Cite Appletons\'', 'Appletons'}, } --[[--------------------------< E X P O R T E D T A B L E S >------------------------------------------------ ]] return { DNB_special_patterns = DNB_special_patterns, DNB_template_names = template_names['DNB'], special_patterns = special_patterns, whitelist = whitelist, wrapper_templates = wrapper_templates, } 1aa09b54f21ebd45d55c0e11bec8783c21d7a4fa Template:Link note 10 132 279 2022-08-23T14:39:36Z Canopus >Jonesey95 0 Fix too small font per [[MOS:FONTSIZE]] when this template appears in reflists, e.g. at [[David Deutsch]]. Reflists are already at 90% of base font size. wikitext text/x-wiki <span style="font-size:0.95em; font-size:95%; color:#555">({{{note|}}})</span><includeonly>{{#if:{{{cat|}}}|{{DMCA|{{{cat|}}}|from|{{{date|}}}}}}}</includeonly><noinclude>{{documentation}}</noinclude> 86089fa5a81775a10f0a53b58426a73b5c9a69ba Template:Short description 10 65 145 2022-08-23T19:55:08Z Canopus >Fayenatic london 0 Exclude category generation in user space, see [[Wikipedia:Categories_for_discussion/Log/2022_August_13#Category:User_pages_with_short_description]] – thanks to [[user:Vanisaac]] for sandboxing this wikitext text/x-wiki {{#ifeq:{{lc:{{{1|}}}}}|none|<nowiki /><!--Prevents whitespace issues when used with adjacent newlines-->|<div class="shortdescription nomobile noexcerpt noprint searchaux" style="display:none">{{{1|}}}{{SHORTDESC:{{{1|}}}|{{{2|}}}}}</div>}}<includeonly>{{#ifeq:{{pagetype |defaultns = all |user=exclude}}|exclude||[[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with short description{{#ifeq:{{{pagetype}}}|Disambiguation pages|s}}]]}}</includeonly><!-- Start tracking -->{{#invoke:Check for unknown parameters|check|unknown={{Main other|[[Category:Pages using short description with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Short description]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | 2 | pagetype | bot |plural }}<!-- -->{{#ifexpr: {{#invoke:String|len|{{{1|}}}}}>100 | [[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with long short description]]}}<!-- -->{{Short description/lowercasecheck|{{{1|}}}}}<!-- -->{{Main other |{{SDcat |sd={{{1|}}} }} }}<noinclude> {{Documentation}} </noinclude> a9562f8e6077b84b83132612ac9a5b37c58485b3 Category:Pages with ignored display titles 14 29 63 2022-08-27T14:24:00Z SpaceMan 2 Created page with "Home page" wikitext text/x-wiki Home page 9521dba25709a79ede4a34b50471419774c41099 Astronomy Database portal 0 30 64 2022-08-27T14:31:12Z SpaceMan 2 Created page with "==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from CDS ." wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from CDS . d93cb94f20b5f7f0fce94caab73da93eda806d3a 65 64 2022-08-27T14:32:19Z SpaceMan 2 wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from [https://cds.u-strasbg.fr/ CDS] . 67b4aefc8fe0d54785a275aefa92aea5ebabf20b 71 65 2022-08-27T15:06:51Z SpaceMan 2 /* Astronomy Database Portal */ wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from [https://cds.u-strasbg.fr/ CDS] . ==Star== [https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major] 431812e74fb6cade65be446d4cea72a4dd2aaf4d VY Canis Major 0 31 67 2022-08-27T15:01:57Z SpaceMan 2 VY Canis Major wikitext text/x-wiki ==Definition== VY Canis Majoris or VY CMa is a red [[Hypergiant sta]]. It is located in the constellation [[Canis Major]]. It is one of the largest and brightest red hypergiants observed so far. It has a diameter of 1800 solar radii. This star emits energy very quickly and therefore, only exists for a few million years. It is estimated to be 4900 light years away from Earth. This star shows periodic light changes that last for approximately 2200 days. ==The crimson star== The first known recorded observation of VY Canis Majoris is in the star catalogue of Jérôme Lalande, who recorded it on 7th March, 1801. Since 1847, VY CMa has been known to be a crimson star. Originally, University of Minnesota Professor Roberta M. Humphreys approximated that the radius of VY CMa is 1800-2100 times that of the Sun. This would make it the largest known star based on its radius. ==Surface== This star also illustrates the conceptual problem of defining the "surface" of very large stars. This is very important for multiple reasons, including determining its radius and thus its size. It is a hundred thousand times less dense than the atmosphere of Earth (air) at sea level. Its average density is 0.000005 to 0.000010 kg per m³. Additionally, the star is constantly losing mass at an astounding rate. The boundary of such a star is usually defined by its "[[Rosseland Radius]]", which is based on its opaqueness to light. 48bb33dd2e981b39c6321e7f4feb688f22f249f5 69 67 2022-08-27T15:05:11Z SpaceMan 2 /* Definition */ wikitext text/x-wiki [[File:VY Canis Major.jpg|thumb|VY Canis Major]] ==Definition== VY Canis Majoris or VY CMa is a red [[Hypergiant sta]]. It is located in the constellation [[Canis Major]]. It is one of the largest and brightest red hypergiants observed so far. It has a diameter of 1800 solar radii. This star emits energy very quickly and therefore, only exists for a few million years. It is estimated to be 4900 light years away from Earth. This star shows periodic light changes that last for approximately 2200 days. ==The crimson star== The first known recorded observation of VY Canis Majoris is in the star catalogue of Jérôme Lalande, who recorded it on 7th March, 1801. Since 1847, VY CMa has been known to be a crimson star. Originally, University of Minnesota Professor Roberta M. Humphreys approximated that the radius of VY CMa is 1800-2100 times that of the Sun. This would make it the largest known star based on its radius. ==Surface== This star also illustrates the conceptual problem of defining the "surface" of very large stars. This is very important for multiple reasons, including determining its radius and thus its size. It is a hundred thousand times less dense than the atmosphere of Earth (air) at sea level. Its average density is 0.000005 to 0.000010 kg per m³. Additionally, the star is constantly losing mass at an astounding rate. The boundary of such a star is usually defined by its "[[Rosseland Radius]]", which is based on its opaqueness to light. 03d971b276b3e76f93f238cce3d20f4813aacc8d 70 69 2022-08-27T15:05:41Z SpaceMan 2 Protected "[[VY Canis Major]]" ([Edit=Allow only administrators] (indefinite)) wikitext text/x-wiki [[File:VY Canis Major.jpg|thumb|VY Canis Major]] ==Definition== VY Canis Majoris or VY CMa is a red [[Hypergiant sta]]. It is located in the constellation [[Canis Major]]. It is one of the largest and brightest red hypergiants observed so far. It has a diameter of 1800 solar radii. This star emits energy very quickly and therefore, only exists for a few million years. It is estimated to be 4900 light years away from Earth. This star shows periodic light changes that last for approximately 2200 days. ==The crimson star== The first known recorded observation of VY Canis Majoris is in the star catalogue of Jérôme Lalande, who recorded it on 7th March, 1801. Since 1847, VY CMa has been known to be a crimson star. Originally, University of Minnesota Professor Roberta M. Humphreys approximated that the radius of VY CMa is 1800-2100 times that of the Sun. This would make it the largest known star based on its radius. ==Surface== This star also illustrates the conceptual problem of defining the "surface" of very large stars. This is very important for multiple reasons, including determining its radius and thus its size. It is a hundred thousand times less dense than the atmosphere of Earth (air) at sea level. Its average density is 0.000005 to 0.000010 kg per m³. Additionally, the star is constantly losing mass at an astounding rate. The boundary of such a star is usually defined by its "[[Rosseland Radius]]", which is based on its opaqueness to light. 03d971b276b3e76f93f238cce3d20f4813aacc8d File:VY Canis Major.jpg 6 32 68 2022-08-27T15:04:07Z SpaceMan 2 Uploaded own work with UploadWizard wikitext text/x-wiki =={{int:filedesc}}== {{Information |description={{en|1=VY Canis Major}} |date=2022-08-27 20:32:42 |source={{own}} |author=[[User:SpaceMan|SpaceMan]] |permission= |other versions= }} =={{int:license-header}}== {{self|cc-by-sa-4.0}} [[Category:Star]] db6fb4412807d83d8706850354079c01c0da829e Canopus 0 37 89 2022-09-01T02:49:57Z Canopus >Prince Pugs 0 ahh I'm pretty stupid don't you think wikitext text/x-wiki {{short description|Bright giant star in the constellation of Carina}} {{Other uses}} {{Starbox begin | name=Canopus }} {{Starbox image | image=[[File:Canopus.jpg|255px]] | caption=An image of Canopus by [[Expedition 6]] }} {{Starbox observe | epoch=J2000 | constell=[[Carina (constellation)|Carina]] | pronounce={{IPAc-en|k|ə|ˈ|n|oʊ|p|ə|s}}<ref>{{OED|Canopus}}</ref> | ra={{RA|06|23|57.10988}}<ref name="van Leeuwen2007">{{cite journal | title=Validation of the new Hipparcos reduction | last1=van Leeuwen | first1=F. | journal=Astronomy and Astrophysics | volume=474 | issue=2 | pages=653–664 | date=2007 | arxiv=0708.1752 | bibcode=2007A&A...474..653V | doi=10.1051/0004-6361:20078357 | s2cid=18759600 }} [http://webviz.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b48255b3&-out.add=.&-source=I/311/hip2&recno=30362 Vizier catalog entry ]</ref> | dec={{DEC|-52|41|44.3810}}<ref name="van Leeuwen2007"/> | appmag_v=−0.74<ref name="Ducati 2002">{{cite journal | title=Catalogue of Stellar Photometry in Johnson's 11-color system | last1=Ducati | first1=J. R. | journal=CDS/ADC Collection of Electronic Catalogues | volume=2237 | pages=0 | date=2002 | bibcode=2002yCat.2237....0D }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b360304a&-out.add=.&-source=II/237/colors&recno=1155 Vizier catalog entry ]</ref> }} {{Starbox character | type= | class=A9&nbsp;II<ref name=perkins>{{cite journal|bibcode=1989ApJS...69..301G|title=The early F-type stars – Refined classification, confrontation with Stromgren photometry, and the effects of rotation|journal=Astrophysical Journal Supplement Series|volume=69|pages=301|last1=Gray|first1=R. O.|last2=Garrison|first2=R. F.|year=1989|doi=10.1086/191315}}</ref><ref>{{cite journal|bibcode=1993ASPC...45...59L|title=A Spectroscopic Study of High Galactic Latitude F Supergiant Stars|journal=Luminous High-Latitude Stars. The International Workshop on Luminous High-Latitude Stars|volume=45|pages=59|last1=Lopez-Cruz|first1=O.|last2=Garrison|first2=R. F.|year=1993}}</ref> | b-v=+0.15<ref name="Ducati 2002"/> | u-b=+0.10<ref name="Ducati 2002"/> | variable= }} {{Starbox astrometry | radial_v={{val|20.3|0.5}}<ref name="Gontcharov 2007">{{cite journal | title=Pullkovo Compilation of Radial Velocities for 39495 Hipparcos stars in a common system | last1=Gontcharov | first1=G. A. | journal=Astronomy Letters | volume=32 | issue=1 | pages=759–771 | date=2007 | bibcode=2006AstL...32..759G | doi=10.1134/S1063773706110065|arxiv = 1606.08053 | s2cid=119231169 }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b5f60fbd&-out.add=.&-source=III/252/table8&recno=9232 Vizier catalog entry ]</ref> | prop_mo_ra=19.93<ref name="van Leeuwen2007"/> | prop_mo_dec=23.24<ref name="van Leeuwen2007"/> | parallax=10.55 | p_error=0.56 | parallax_footnote=<ref name="van Leeuwen2007"/> | absmag_v=–5.71<ref name=smiljanic2006/> |arxiv = 1606.08053 }} {{Starbox detail | metal_fe=–0.07<ref name=smiljanic2006/> | mass={{Val|8.0|0.3}}<ref name=vlti>{{cite journal|bibcode=2013MNRAS.434..437C|arxiv=1306.3288|title=Fundamental parameters of 16 late-type stars derived from their angular diameter measured with VLTI/AMBER|journal=Monthly Notices of the Royal Astronomical Society|volume=434|issue=1|pages=437–450|last1=Cruzalèbes|first1=P.|last2=Jorissen|first2=A.|last3=Rabbia|first3=Y.|last4=Sacuto|first4=S.|last5=Chiavassa|first5=A.|last6=Pasquato|first6=E.|last7=Plez|first7=B.|last8=Eriksson|first8=K.|last9=Spang|first9=A.|last10=Chesneau|first10=O.|year=2013|doi=10.1093/mnras/stt1037|s2cid=49573767}}</ref>&nbsp;(2013)<br/>{{val|10.1|0.1}}<ref name=Tetzlaff2011/>&nbsp;(2011) | radius={{Val|71|4}}<ref name=vlti/>&nbsp;(2013)<br>{{val|73.3|5.2}}<ref name=DomicianoDeSouza>{{cite journal|doi=10.1051/0004-6361/202140478|title=Refined fundamental parameters of Canopus from combined near-IR interferometry and spectral energy distribution|year=2021|last1=Domiciano De Souza|first1=A.|last2=Zorec|first2=J.|last3=Millour|first3=F.|last4=Le Bouquin|first4=J.-B.|last5=Spang|first5=A.|last6=Vakili|first6=F.|journal=Astronomy & Astrophysics|volume=654|pages=A19|arxiv=2109.07153|bibcode=2021A&A...654A..19D|s2cid=237513623}}</ref>&nbsp;(2021) | gravity={{Val|1.70|0.05}}<ref name=DomicianoDeSouza/> | rotational_velocity=9<ref name=ayres2018/> | rotation={{val|298|u=days|p=≥}}<ref name=Testa2004/> | luminosity=10,700<ref name=vlti/> | temperature=7,400<ref name=ayres2018>{{cite journal |bibcode=2018ApJ...854...95A |title=Cracking the Conundrum of F-supergiant Coronae |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |year=2018 |volume=854 |issue=2 |page=95 |doi=10.3847/1538-4357/aaa6d7 |arxiv=1802.02552 |s2cid=119101035 }}</ref> | age_myr = {{val|25.1|2.5}}<ref name=Tetzlaff2011>{{cite journal | title=A catalogue of young runaway Hipparcos stars within 3 kpc from the Sun | last1=Tetzlaff | first1=N. | last2=Neuhäuser | first2=R. | last3=Hohle | first3=M. M. | journal=Monthly Notices of the Royal Astronomical Society | volume=410 | issue=1 | pages=190–200 | date=January 2011 | doi=10.1111/j.1365-2966.2010.17434.x | arxiv=1007.4883 | bibcode=2011MNRAS.410..190T | s2cid=118629873 }}</ref> }} {{Starbox catalog | names={{odlist | name=Suhayl | name2=Suhel | name3=Suhail | B=α Carinae | CPD=−52°1941 | FK5=245 | HD=45348 | HIP=30438 | HR=2326 | SAO=234480| GC=8302 }}<ref name=SIMBAD>{{cite simbad | title=alf Car | access-date=2019-03-09 }}</ref> }} {{Starbox reference | Simbad=canopus }} {{Starbox end}} '''Canopus''' is the brightest star in the southern [[constellation]] of [[Carina (constellation)|Carina]] and the [[list of brightest stars|second-brightest star]] in the [[night sky]]. It is also [[Bayer designation|designated]] '''α&nbsp;Carinae''', which is [[Latinisation of names|Latinised]] to '''Alpha&nbsp;Carinae'''. With a [[visual apparent magnitude]] of −0.74, it is outshone only by [[Sirius]]. Located around {{val|310|ul=light-years}} from the [[Sun]], Canopus is a [[bright giant]] of [[spectral type A9]], so it is essentially white when seen with the naked eye. It has a luminosity over 10,000 times the [[luminosity of the Sun]], is eight times as [[mass of the Sun|massive]], and has expanded to 71 times the [[Sun's radius]]. Its enlarged [[photosphere]] has an [[effective temperature]] of around {{val|7,400|fmt=commas|u=K}}. Canopus is undergoing [[stellar core|core]] [[helium fusion|helium burning]] and is currently in the so-called [[blue loop]] phase of its [[stellar evolution|evolution]], having already passed through the [[red-giant branch]] after exhausting the hydrogen in its core. Canopus is a [[X-ray astronomy|source of X-rays]], which are likely being emitted from its [[stellar corona|corona]]. The prominent appearance of Canopus means it has been the subject of mythological lore among many ancient peoples. Its proper name is generally considered to originate from the [[Greek mythology|mythological]] [[Canopus (mythology)|Canopus]], who was a navigator for [[Menelaus]], king of [[Sparta]]. The [[acronychal rising]] marked the date of the Ptolemaia festival in Egypt. In ancient India, it was named [[Agastya]] after the revered [[Vedas|Vedic]] sage. For Chinese astronomers, it was known as the [[Old Man of the South Pole]]. ==Nomenclature== The name ''Canopus'' is a Latinisation of the [[Ancient Greek]] name Κάνωβος/Kanôbos, recorded in Claudius Ptolemy's ''[[Almagest]]'' (c.150 AD). Eratosthenes used the same spelling.<ref name="ridpathCr"/> Hipparchos wrote it as Κάνωπος. [[John Flamsteed]] wrote Canobus,<ref>{{cite book|last=Flamsteed|first=John|title=Atlas coelestis|location=London, United Kingdom|date=1729|pages=Constellation Map of Southern Hemisphere|url=http://lhldigital.lindahall.org/u?/astro_atlas,1191}}</ref> as did [[Edmond Halley]] in his 1679 ''Catalogus Stellarum Australium''.<ref name="Halley 1679">{{cite book|last=Halley|first=Edmond|title=Catalogus stellarum australium; sive, Supplementum catalogi Tychenici, exhibens longitudines et latitudines stellarum fixarum, quae, prope polum Antarcticum sitae, in horizonte Uraniburgico Tychoni inconspicuae fuere, accurato calculo ex distantiis supputatas, & ad annum 1677 completum correctas...Accedit appendicula de rebus quibusdam astronomicis|publisher=T. James|location=London|date=1679|pages=30|url=http://babel.hathitrust.org/cgi/pt?id=mdp.39015007000170;view=1up;seq=41;size=150}}</ref> The name has two possible derivations, both listed in [[Richard Hinckley Allen]]'s seminal ''[[Star Names: Their Lore and Meaning]]''. * [[Argo Navis]] was the ship used by [[Jason]] and the Argonauts in the legend of the [[Trojan War]]. The brightest star in the constellation was given the name of a ship's pilot from another Greek legend: [[Canopus (mythology)|Canopus]], pilot of [[Menelaus]]' ship on his quest to retrieve [[Helen of Troy]] after she was taken by [[Paris (mythology)|Paris]].<ref name="hinkley63">{{cite book|first=Richard Hinckley|last=Allen|author-link=Richard Hinckley Allen|date=1963|orig-year=1899|title=Star Names: Their Lore and Meaning|pages=[https://archive.org/details/starnamestheirlo00alle/page/67 67–72]|edition=Revised|publisher=Dover Publications|location=New York|isbn=0-486-21079-0|url-access=registration|url=https://archive.org/details/starnamestheirlo00alle/page/67}}</ref> * A ruined ancient Egyptian port named [[Canopus, Egypt|Canopus]] lies near the mouth of the [[Nile]], site of the [[Battle of the Nile]]. It is speculated that its name is derived from the Egyptian [[Coptic language|Coptic]] ''Kahi Nub'' ("Golden Earth"), which refers to how Canopus would have appeared near the horizon in [[ancient Egypt]], reddened by atmospheric extinction from that position.<ref name="hinkley63"/><ref name=lynn1905>{{cite journal |bibcode=1905Obs....28..289L |title=The brightest fixed star and its name |last1=Lynn |first1=W. T. |journal=The Observatory |year=1905 |volume=28 |page=289 }}</ref> In 2016, the [[International Astronomical Union]] organized a [[IAU Working Group on Star Names|Working Group on Star Names]] (WGSN) to catalog and standardize proper names for stars.<ref name="WGSN">{{cite web | url=https://www.iau.org/science/scientific_bodies/working_groups/280/ | title=IAU Working Group on Star Names (WGSN) | website=iau.org | publisher=[[International Astronomical Union]] | access-date=22 May 2016}}</ref> The WGSN's first bulletin of July 2016 included a table of the first two batches of names approved by the WGSN, which included ''Canopus'' for this star.<ref name="WGSN1">{{cite web | url=https://www.iau.org/static/science/scientific_bodies/working_groups/280/WGSN_bulletin1.pdf | title=Bulletin of the IAU Working Group on Star Names, No. 1 | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06 }}</ref> Canopus is now included in the ''IAU Catalog of Star Names''.<ref name="IAU-CSN">{{cite web | url=https://www.iau.org/public/themes/naming_stars/ | title=IAU Catalog of Star Names | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06}}</ref> Canopus traditionally marked the rudder of the ship [[Argo Navis]].<ref>{{cite journal | title = On Frederick de Houtman's Catalogue of Southern Stars, and the Origin of the Southern Constellations | last1= Knobel|first1=E. B. |journal = [[Monthly Notices of the Royal Astronomical Society]] | volume= 77| issue= 5 | pages=414–432 [422] | bibcode = 1917MNRAS..77..414K |date=1917 | doi=10.1093/mnras/77.5.414| doi-access=free }}</ref> German celestial cartographer [[Johann Bayer]] gave it—as the brightest star in the constellation—the [[Bayer designation|designation]] of ''α&nbsp;Argus'' ([[Latinisation of names|Latinised]] to ''Alpha Argus'') in 1603. In 1763, French astronomer [[Nicolas Louis de Lacaille]] divided the huge constellation into three smaller ones,<ref name=Glass2012>{{cite book | title=Nicolas-Louis De La Caille, Astronomer and Geodesist | first=Ian Stewart | last=Glass | date=November 17, 2012 | page=73 | isbn=9780191649608 | publisher=OUP Oxford | url=https://www.google.com/books/edition/Nicolas_Louis_De_La_Caille_Astronomer_an/eZjlHAIBeRAC?hl=en&gbpv=1&pg=PT73 }}</ref> and hence Canopus became ''α&nbsp;Carinae'' ([[Latinisation of names|Latinised]] to ''Alpha Carinae''). It is listed in the [[Bright Star Catalogue]] as HR 2326, the [[Henry Draper Catalogue]] as HD 45348, and the [[Hipparcos catalogue]] as HIP 30438.<ref name=SIMBAD/> Flamsteed did not number this southern star, but [[Benjamin Apthorp Gould]] gave it the number 7 (7 G. Carinae) in his ''Uranometria Argentina''.<ref name=Gould1878>{{cite journal | title=Uranometria Argentina: Brightness and position of every fixed star, down to the seventh magnitude, within one hundred degrees of the South Pole; with atlas | last=Gould | first=Benjamin Apthorp | journal=Resultados del Observatorio Nacional Argentino | volume=1 | page=140 | date=1878 | bibcode=1879RNAO....1....1G }}</ref> An occasional name seen in English is ''Soheil'', or the feminine Soheila; in Turkish is ''Süheyl'', or the feminine Süheyla, from the Arabic name for several bright stars, سهيل ''suhayl'',<ref name="hinkley63"/> and Canopus was known as Suhel {{IPAc-en|'|s|uː|h|E|l}} in medieval times.<ref name=kunitzsch/> Alternative spellings include Suhail, Souhail, Suhilon, Suheyl, Sohayl, Suhayil, Shoel, Sohil, Soheil, Sahil, Suhayeel, Sohayil, Sihel, and Sihil.<ref name="hinkley63"/> An alternative name was ''Wazn'' "weight" or ''Haḍar'' "ground", possibly related to its low position near the horizon.<ref name="hinkley63"/> Hence comes its name in the ''[[Alfonsine tables]]'', Suhel ponderosus, a Latinization of ''Al Suhayl al Wazn''.<ref name="hinkley63"/> Its Greek name was revived during the [[Renaissance]].<ref name=kunitzsch>{{cite book |last1=Kunitzsch|first1=Paul |last2=Smart|first2=Tim |date = 2006|title = A Dictionary of Modern star Names: A Short Guide to 254 Star Names and Their Derivations |edition = 2nd rev. |publisher = Sky Publishing Corporation |location = Cambridge, Massachusetts |isbn = 978-1-931559-44-7 |page = 23}}</ref> ==Observation== [[File:Carina constellation map.svg|thumb|left|The constellation [[Carina (constellation)|Carina]] with Canopus towards the right (west)]] The Spanish Muslim astronomer [[Ibn Rushd]] went to [[Marrakesh]] (in Morocco) to observe the star in 1153, as it was invisible in his native [[Córdoba, Spain|Córdoba]], [[Al-Andalus]]. He used the different visibility in different latitudes to argue that the [[Spherical Earth|earth is round]], following [[Spherical Earth#Aristotle|Aristotle's argument]] which held that such an observation was only possible if the earth was a relatively small sphere.<ref name=ibn_rushd>{{cite encyclopedia|first1=Juan|last1=Vernet|author-link1=Juan Vernet|first2=Julio|last2=Samsó|author-link2=Julio Samsó |title=The development of Arabic science in Andalusia |page=264|editor=[[Roshdi Rashed]]|encyclopedia=Encyclopedia of the History of Arabic Science | date=1996|publisher=Routledge|isbn=978-0-415-12410-2|oclc=912501823}}</ref> English explorer [[Robert Hues]] brought Canopus to the attention of European observers in his 1592 work ''Tractatus de Globis'', along with [[Achernar]] and [[Alpha Centauri]], noting:<blockquote>"Now, therefore, there are but three [[First-magnitude star|Stars of the first magnitude]] that I could perceive in all those parts which are never seene here in England. The first of these is that bright Star in the sterne of [[Argo Navis|Argo]] which they call Canobus. The second is in the end of [[Eridanus (constellation)|Eridanus]]. The third is in the right foote of the [[Centaurus|Centaure]]."<ref>Knobel, p. 416.</ref></blockquote> [[File:Vela and Surrounding Constellations (ground-based image).jpg|right|thumb|Wide angle view showing Canopus and other prominent stars with the Milky Way|alt=A field of stars against the Milky Way background with the prominent stars and constellations labelled]] In the [[Southern Hemisphere]], Canopus and [[Sirius]] are both visible high in the sky simultaneously, and reach a [[meridian (astronomy)|meridian]] just {{val|21|u=minutes}} apart. Brighter than [[first-magnitude star|first magnitude]], Canopus can be seen by naked eye in the early twilight. Mostly visible in mid to late summer in the Southern Hemisphere, Canopus [[Culmination|culminates]] at midnight on December 27,<ref name="motz" /> and at 9 PM on February 11.<ref name="Schaaf257">Schaaf, p. 257.</ref> When seen from latitudes south of {{DEC|37|18}}&nbsp;S, Canopus is a [[circumpolar star]]. Since Canopus is so far south in the sky, it never rises in mid- to far-northern latitudes; in theory the northern limit of visibility is latitude {{DEC|37|18}} north. This is just south of [[Athens]], [[Richmond, Virginia]] (USA), and [[San Francisco]], and very close to [[Seville]] and [[Agrigento]]. It is almost exactly the latitude of [[Lick Observatory]] on [[Mount Hamilton (California)|Mt. Hamilton, California]], from which it is readily visible because of the effects of elevation and [[atmospheric refraction]], which add another degree to its apparent altitude. Under ideal conditions, it can be spotted as far north as latitude {{DEC|37|31}} from the Pacific coast.<ref>D. Gieringer, "Exploring the Tropic of Canopus", ''Astronomy'', December 1985, p.24.</ref> Another northernmost record of visibility came from [[Mount Nemrut]] in Turkey, latitude {{DEC|37|59}}.<ref>{{cite web |last1=Tezel |first1=Tunç |author-link=Tunç Tezel |url=http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |title=Zodiacal Light and Nemrut Heritage |work=The World At Night (TWAN) |access-date=17 March 2014 |date=8 Oct 2013 |archive-url=https://web.archive.org/web/20140317134955/http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |archive-date=17 March 2014 |url-status=dead }}</ref> It is more easily visible in places such as the Gulf Coast and Florida, and the island of [[Crete]] (Greece) where the best season for viewing it around 9 p.m. is during late January and early February.<ref name="motz">{{cite book|last1=Motz|first1=Lloyd|last2=Nathanson|first2=Carol|title=The Constellations: An Enthusiast's Guide to the Night Sky|publisher=Aurum Press|location=London, United Kingdom|date=1991|pages=376–77|isbn=1-85410-088-2}}</ref> Canopus has a B–V [[color index]] of +0.15—where 0 is a blue-white—indicating it is essentially white, although it has been described as yellow-white. Canopus' spectral type has been given as F0 and the incrementally warmer A9. It is less yellow than [[Altair]] or [[Procyon]], with indices measured as 0.22 and 0.42, respectively.<ref name=Hoffleit1991>{{cite book | title=Bright Star Catalogue | edition=5th Revised | last1=Hoffleit | first1=D. | last2=Warren Jr. | first2=W. H. | date=1991 | publisher=[[Centre de Données astronomiques de Strasbourg|CDS]] }}</ref> Some observers may have perceived Canopus as yellow-tinged because it is low in the sky and hence subject to atmospheric effects.<ref name="Schaaf112">Schaaf, pp. 112–13.</ref> [[Patrick Moore]] said that it never appeared anything but white to him.<ref name="moore2000">{{cite book | first1=Patrick | last1=Moore | title=Exploring the night sky with binoculars | edition=4th | publisher=Cambridge University Press | year=2000 | isbn=9780521793902 | page=[https://archive.org/details/exploringnightsk00moor/page/69 69] | url=https://archive.org/details/exploringnightsk00moor| url-access=registration }}</ref> The [[bolometric correction]] for Canopus is 0.00,<ref name=smiljanic2006/> indicating that the visual [[absolute magnitude]] and bolometric absolute magnitude are equal. Canopus was previously proposed to be a member of the [[Scorpius–Centaurus association]], however it is not located near the subgroups of that association, and has not been included as a Sco-Cen member in kinematic studies that used [[Hipparcos]] astrometric data.<ref name="deZeeuw">{{cite journal|last1=de Zeeuw|first1=P.T. |last2=Hoogerwerf|first2=R. |last3=de Bruijne|first3=J.H.J |last4=Brown|first4=A.G.A |last5=Blaauw|first5=A. |date=1999|title=A HIPPARCOS Census of the Nearby OB Associations |journal=The Astronomical Journal |volume=117 |issue=1 |pages=354–399|bibcode=1999AJ....117..354D |doi=10.1086/300682|arxiv = astro-ph/9809227 |s2cid=16098861 }}</ref> Canopus is not thought to be a member of any nearby young stellar groups.<ref name=mamajek>{{cite journal | url=https://figshare.com/articles/Canopus_B_A_Candidate_Common_Proper_Motion_Companion_to_the_Second_Brightest_Star/1132696 | title=Canopus B: A Candidate Common Proper Motion Companion to the Second Brightest Star | last=Mamajek | first=Eric | year=2014 | publisher=Figshare | doi=10.6084/m9.figshare.1132696.v3 | access-date=2020-09-10 }}</ref> In 2014, astronomer Eric Mamajek reported that an extremely magnetically active M dwarf (having strong coronal X-ray emission), 1.16 degrees south of Canopus, appears to share a [[common proper motion]] with Canopus. The projected separation of the M dwarf 2MASS J06234738-5351131 ("Canopus B") is approximately 1.9 parsecs. However, despite this large separation, it is still within the estimated tidal radius (2.9 parsecs) for the massive star Canopus.<ref name="mamajek"/> No star closer than Canopus is more luminous than it, and it has been the brightest star in Earth's night sky during three epochs over the past four million years. Other stars appear brighter only during relatively temporary periods, during which they are passing the Solar System much closer than Canopus. About 90,000 years ago, [[Sirius]] moved close enough that it became brighter than Canopus, and that will remain so for another 210,000 years. But in 480,000 years, as Sirius moves further away and appears fainter, Canopus will once again be the brightest, and will remain so for a period of about 510,000 years.<ref name="tomkin98">{{cite journal|last=Tomkin|first=Jocelyn|date=April 1998|title=Once and Future Celestial Kings|journal=Sky and Telescope|volume=95|issue=4|pages=59–63|bibcode=1998S&T....95d..59T}}</ref><!-- this all comes from same paper --> ===Role in navigation=== The southeastern wall of the [[Kaaba]] in [[Mecca]] is aligned with the rising point of Canopus, and is also named ''Janūb''.<ref>{{cite book|author=George Nicholas Atiyeh|title=The Book in the Islamic World: The Written Word and Communication in the Middle East|url=https://books.google.com/books?id=t4LEfpCW_kQC|date=1 January 1995|publisher=SUNY Press|isbn=978-0-7914-2473-5}}</ref> The [[Negev Bedouin|Bedouin]] people of the [[Negev]] and [[Sinai Peninsula|Sinai]] knew Canopus as ''Suhayl'', and used it and [[Polaris]] as the two principal stars for navigation at night. Because it disappears below the horizon in those regions, it became associated with a changeable nature, as opposed to always-visible Polaris, which was circumpolar and hence 'steadfast'.<ref>{{cite journal |last=Bailey |first=Clinton |date=1974 |title=Bedouin Star-Lore in Sinai and the Negev |journal=Bulletin of the School of Oriental and African Studies, University of London |volume=37 |issue=3 |pages=580–96 |type=abstract |doi=10.1017/S0041977X00127491 |jstor=613801|s2cid=131527348 }}</ref> The south [[celestial pole]] can be approximately located using Canopus and another bright star, [[Achernar]], as the three make an [[equilateral triangle]]. Canopus sits on an imaginary line that extends {{DEC|36}} one way to Sirius and {{DEC|37}} to the south celestial pole.<ref>{{Cite book| last1 = Heifetz| first1 = Milton| last2 = Tirion| first2 = Wil| title = A Walk Through the Heavens: A Guide to Stars and Constellations and Their Legends | date = 2007| publisher = [[Cambridge University Press]]| location = Cambridge | page = 38 | isbn=978-1-139-46138-2}}</ref> Canopus's brightness and location well off the [[ecliptic]] make it useful for space navigation. Many spacecraft carry a special camera known as a "Canopus [[star tracker|Star Tracker]]" plus a Sun sensor for [[Orientation (geometry)|attitude]] determination. [[Mariner 4]] used Canopus for [[Spin-stabilisation|second axis stabilisation]] (after locking on the Sun) in 1964, the first time a star had been used.<ref>{{cite book |last1=United States. National Aeronautics and Space Administration. Scientific and Technical Information Division |title=Astronautics and Aeronautics, 1964: Chronology on Science, Technology and Policy |date=1965 |publisher=Scientific and Technical Information Division, National Aeronautics and Space Administration |page=398 |url=https://books.google.com/books?id=ckkCAAAAIAAJ&pg=PA398}}</ref> ==Spectrum== Canopus was little-studied by western scientists before the 20th century. It was given a spectral class of F in 1897, an early use of this extension to [[Secchi class]] I, applied to those stars where the hydrogen lines are relatively weak and the [[calcium K line]] relatively strong.<ref>{{cite journal |bibcode=1897ApJ.....6..349P |title=Spectra of bright southern stars |last1=Pickering |first1=E. C. |last2=Cannon |first2=A. J. |journal=The Astrophysical Journal |year=1897 |volume=6 |page=349 |doi=10.1086/140407 }}</ref> It was given as a standard star of F0 in the [[Henry Draper Catalogue]], with the spectral type F0 described as having hydrogen lines half the strength of an A0 star and the calcium K line three times as strong as Hδ.<ref name=hd>{{cite journal |bibcode=1918AnHar..92....1C |title=The Henry Draper catalogue : 4h, 5h and 6h |last1=Cannon |first1=Annie Jump |last2=Pickering |first2=Edward Charles |journal=Annals of Harvard College Observatory |year=1918 |volume=92 |page=1 }}</ref> American astronomer [[Jesse L. Greenstein|Jesse Greenstein]] was interested in stellar spectra and used the newly built [[Otto Struve Telescope]] at [[McDonald Observatory]] to analyze the star's spectrum in detail.<ref>{{cite book |last1=Trimble |first1=Virginia | first2= Thomas R. |last2=Williams | first3= Katherine | last3=Bracher| first4= Richard | last4=Jarrell| first5=Jordan D.| last5= Marché| first6=F. Jamil | last6=Ragep |title=Biographical Encyclopedia of Astronomers |date=2007 |publisher=Springer Science & Business Media |location=New York, New York |isbn=978-0-387-30400-7 |page=438 |url=https://books.google.com/books?id=t-BF1CHkc50C&pg=PA438}}</ref> In a 1942 paper, he reported that the spectrum is dominated by strong broad hydrogen lines. There are also [[absorption line]]s of carbon, nitrogen, oxygen, sulphur, iron, and many ionised metals.<ref name=greenstein1942>{{cite journal |bibcode=1942ApJ....95..161G |title=The Spectrum of α Carinae |last1=Greenstein |first1=Jesse L. |journal=The Astrophysical Journal |year=1942 |volume=95 |page=161 |doi=10.1086/144382 }}</ref> It was studied in the [[ultraviolet]] by an early astronomical satellite, [[Gemini XI]] in 1966. The UV spectra were considered to be consistent with an F0 [[Supergiant star|supergiant]] having a temperature of {{val|6,900|fmt=commas|u=K}}, the accepted parameters for Canopus at the time.<ref name=kondo1970>{{cite journal |bibcode=1970ApJ...159..927K |title=Ultraviolet Spectrophotometry of Canopus from Gemini XI |last1=Kondo |first1=Y. |last2=Henize |first2=K. G. |last3=Kotila |first3=C. L. |journal=The Astrophysical Journal |year=1970 |volume=159 |page=927 |doi=10.1086/150370 }}</ref> New Zealand-based astronomers [[John Hearnshaw]] and Krishna Desikachary examined the spectrum in greater detail, publishing their results in 1982.<ref>{{cite journal |title=The spectrum of Canopus | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 198 | year= 1982 | issue= 2 | pages= 311–320 | doi= 10.1093/mnras/198.2.311 | bibcode=1982MNRAS.198..311H| doi-access= free }}</ref><ref>{{cite journal |title=The spectrum of Canopus II - Analysis and composition | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 201 | year= 1982 | issue= 3 | pages= 707–721 | doi= 10.1093/mnras/201.3.707 | bibcode=1982MNRAS.201..707D| doi-access= free }}</ref> When [[luminosity class]]es were added to the MK spectral classification scheme, Canopus was assigned class Iab indicating an intermediate luminosity supergiant. This was based on the relative strengths of certain spectral lines understood to be sensitive to the luminosity of a star.<ref name=devaucoleurs>{{cite journal|title=Spectral types and luminosities of B, A and F southern stars|author=de Vaucouleurs, A.|journal=Monthly Notices of the Royal Astronomical Society|volume=117|page=449|date=1957|issue=4|bibcode=1957MNRAS.117..449D|doi=10.1093/mnras/117.4.449|doi-access=free}}</ref> In the [[Bright Star Catalogue]] 5th edition it is given the spectral class F0II, the luminosity class indicating a [[bright giant]].<ref name=bsc>{{cite book |bibcode=1991bsc..book.....H |year=1991 |title=The Bright star catalogue |last1=Hoffleit |first1=Dorrit |last2=Jaschek |first2=Carlos }}</ref> [[Balmer line]] profiles and oxygen line strengths indicate the size and luminosity of Canopus.<ref name=kovtyukh2012>{{cite journal |bibcode=2012MNRAS.423.3268K |title=Accurate luminosities from the oxygen λ7771-4 Å triplet and the fundamental parameters of F-G supergiants |last1=Kovtyukh |first1=V. V. |last2=Gorlova |first2=N. I. |last3=Belik |first3=S. I. |journal=Monthly Notices of the Royal Astronomical Society |year=2012 |volume=423 |issue=4 |page=3268 |doi=10.1111/j.1365-2966.2012.21117.x |arxiv=1204.4115 |s2cid=118683158 }}</ref> When the effects of stellar rotation speed on spectral lines are accounted for, the MK spectral class of Canopus is adjusted to A9II.<ref name=perkins/> Its spectrum consists mostly of absorption lines on a visible [[continuous spectrum|continuum]], but some emission has been detected. For example, the [[calcium K line]] have weak emission wings on each side of the strong central absorption line, first observed in 1966. The emission line profiles are usually correlated with the luminosity of the star as described by the [[Wilson-Bappu effect]], but in the case of Canopus they indicate a luminosity much lower than that calculated by other methods.<ref name=warner1966>{{cite journal|title=CA II emission in the spectrum of Canopus|journal=The Observatory |volume=86 |pages=82|date=April 1966|last=Warner |first=B. |bibcode=1966Obs....86...82W }}</ref> More detailed observations have shown that the emission line profiles are variable and may be due to [[plage (astronomy)|plage]] areas on the surface of the star. Emission can also be found in other lines such as the h and k lines of ionised magnesium.<ref name=bappu1984>{{cite journal |bibcode=1984BASI...12..196B |title=CA II K emission in Canopus |last1=Bappu |first1=M. K. V. |last2=Mekkaden |first2=M. V. |last3=Rao |first3=N. K. |journal=Bulletin of the Astronomical Society of India |year=1984 |volume=12 |page=196 }}</ref> ==Distance== Before the launch of the [[Hipparcos]] satellite telescope, distance estimates for Canopus varied widely, from 96 [[light-year]]s to 1200 light-years. The closer distance was derived from parallax measurements of around {{val|33|ul=mas}}.<ref name=vandekamp1943>{{cite journal |title=Note on the Parallax of Canopus|journal=Popular Astronomy |volume=51 |date=1943 |page=172 |last=van de Kamp |first=Peter|bibcode=1943PA.....51..172V }}</ref> The larger distance derives from the assumption of a very bright [[absolute magnitude]] for Canopus.<ref name=vanzyl>{{cite book|author=J.E. van Zyl|title=Unveiling the Universe: An Introduction to Astronomy|url=https://books.google.com/books?id=Cj7uBwAAQBAJ&pg=PA184|date=6 December 2012|publisher=Springer Science & Business Media|isbn=978-1-4471-1037-8|pages=184–}}</ref> Hipparcos established Canopus as being {{val|310|u=light-years}} ({{val|95|ul=parsecs}}) from the [[Solar System]]; this is based on its 2007 [[parallax]] measurement of {{Val|10.43|0.53|ul=mas}}.<ref name="van Leeuwen2007"/> At 95 parsecs, the [[interstellar extinction]] for Canopus is low at 0.26 magnitudes.<ref name=DomicianoDeSouza/> Canopus is too bright to be included in the normal observation runs of the [[Gaia satellite]] and there is no published Gaia parallax for it.<ref name=dr2>{{cite DR2}}</ref> At present the star is drifting further away from the Sun with a [[radial velocity]] of 20&nbsp;km/s. Some 3.1&nbsp;million years ago it made the closest approach to the Sun at a distance of about {{convert|52.87|pc|ly|0|adj=ri0|order=flip|abbr=on|lk=off}}. Canopus is orbiting the Milky Way with a heliocentric velocity of 24.5&nbsp;km/s and a low [[orbital eccentricity|eccentricity]] of 0.065.<ref name=Anderson2012>{{citation | last1=Anderson | first1=E. | last2=Francis | first2=Ch. | title=XHIP: An extended hipparcos compilation | journal=Astronomy Letters | volume=38 | issue=5 | pages=331 | year=2012 | bibcode=2012AstL...38..331A | arxiv=1108.4971 | doi=10.1134/S1063773712050015 | s2cid=119257644 | postscript=. }}</ref> ==Physical characteristics== [[File:Constellation_Carina.jpg|thumb|right|upright|Canopus is the brightest star in the constellation of Carina (top).]] The [[absorption line]]s in the spectrum of Canopus shift slightly with a period of {{val|6.9|u=days}}. This was first detected in 1906 and the [[doppler effect|Doppler]] variations were interpreted as orbital motion.<ref name=curtis1907>{{cite journal |bibcode=1907PASP...19R.259C |title=The orbits of the spectroscopic binaries alpha Carinae, kappa Velorum, and alpha Pavonis |last1=Curtis |first1=H. D. |journal=Publications of the Astronomical Society of the Pacific |year=1907 |volume=19 |page=259 |doi=10.1086/121781 }}</ref> An orbit was even calculated, but no such companion exists and the small radial velocity changes are due to movements in the atmosphere of the star. The maximum observed [[radial velocities]] are only 0.7 to {{val|1.6|ul=km/s}}. Canopus also has a magnetic field that varies with the same period, detected by the [[Zeeman splitting]] of its spectral lines.<ref name=weiss1986>{{cite journal |bibcode=1986A&A...160..243W | title=The magnetic field of Canopus | last=Weiss | first=W. W. | journal= Astronomy and Astrophysics |volume= 160|pages= 243–250 | year=1986}}</ref> Canopus is bright at [[microwave]] wavelengths, one of the few F-class stars to be detected by radio.<ref name=gudel2002>{{cite journal |bibcode=2002ARA&A..40..217G |title=Stellar Radio Astronomy: Probing Stellar Atmospheres from Protostars to Giants |last1=Güdel |first1=Manuel |journal=Annual Review of Astronomy and Astrophysics |year=2002 |volume=40 |pages=217–261 |doi=10.1146/annurev.astro.40.060401.093806 |arxiv=astro-ph/0206436 |s2cid=53633983 }}</ref> The [[rotation period]] of the star is not accurately known, but may be over three hundred days.<ref name=Testa2004>{{cite journal | title=The Density of Coronal Plasma in Active Stellar Coronae | last1=Testa | first1=Paola | last2=Drake | first2=Jeremy J. | last3=Peres | first3=Giovanni | journal=The Astrophysical Journal | volume=617 | issue=1 | pages=508–530 | date=December 2004 | doi=10.1086/422355 | arxiv=astro-ph/0405019 | bibcode=2004ApJ...617..508T | s2cid=17532089 }}</ref> The [[projected rotational velocity]] has been measured at 9&nbsp;km/s.<ref name=ayres2018/> An early [[Interferometry|interferometric]] measurement of its [[angular diameter]] in 1968 gave a [[Limb darkening|limb-darkened]] value of {{val|6.86|ul=mas}}, close to the accepted modern value.<ref>{{cite journal |bibcode=1968ARA&A...6...13B |title=Measurement of Stellar Diameters |last1=Brown |first1=R. Hanbury |journal=Annual Review of Astronomy and Astrophysics |year=1968 |volume=6 |page=13 |doi=10.1146/annurev.aa.06.090168.000305 }}</ref> [[Very-long-baseline interferometry]] has been used to calculate Canopus' angular diameter at {{val|6.9|ul=mas}}. Combined with distance calculated from its Hipparcos parallax, this gives it a radius of 71 times [[Solar radius|that of the Sun]].<ref name=vlti/> If it were at the centre of the Solar System, it would extend 90% of the way to the orbit of [[Mercury (planet)|Mercury]].<ref name=Kalerstars>{{cite web|url=http://stars.astro.illinois.edu/sow/canopus.html|title=Canopus|last=Kaler|first=Jim|work=Stars|publisher=University of Illinois|access-date=8 July 2012|date=26 June 2009}}</ref> The radius and temperature relative to the Sun means that it is 10,700 times more luminous than the Sun, and its position in the [[H-R diagram]] relative to theoretical [[stellar evolution|evolutionary]] tracks means that it is {{Val|8.0|0.3}} times as massive as the Sun.<ref name=vlti/> Measurements of its shape find a 1.1° departure from spherical symmetry.<ref name=cruzalebes2015>{{cite journal |bibcode=2015MNRAS.446.3277C |title=Departure from centrosymmetry of red giants and supergiants measured with VLTI/AMBER |last1=Cruzalèbes |first1=P. |last2=Jorissen |first2=A. |last3=Chiavassa |first3=A. |last4=Paladini |first4=C. |last5=Rabbia |first5=Y. |last6=Spang |first6=A. |journal=Monthly Notices of the Royal Astronomical Society |year=2015 |volume=446 |issue=4 |page=3277 |doi=10.1093/mnras/stu2382 |doi-access=free }}</ref> Canopus is a source of [[X-ray astronomy|X-rays]], which are probably produced by its corona, magnetically heated to several million [[Kelvin]]. The temperature has likely been stimulated by fast rotation combined with strong convection percolating through the star's outer layers.<ref name=ness>{{cite journal|bibcode=2004A&A...427..667N|title=On the sizes of stellar X-ray coronae|journal=Astronomy and Astrophysics|volume=427|issue=2|pages=667–683|last1=Ness|first1=J.-U.|last2=Güdel|first2=M.|last3=Schmitt|first3=J. H. M. M.|last4=Audard|first4=M.|last5=Telleschi|first5=A.|year=2004|doi=10.1051/0004-6361:20040504|arxiv = astro-ph/0407231 |s2cid=11468731}}</ref> The soft X-ray sub-coronal X-ray emission is much weaker than the hard X-ray coronal emission. The same behaviour has been measured in other F-class supergiants such as [[α Persei]] and is now believed to be a normal property of such stars.<ref name=ayres2018/> == Evolution == The spectrum of Canopus indicates that it has exhausted its core hydrogen and [[stellar evolution|evolved]] away from the [[main sequence]], where it spent some 30 million years of its existence as a blue-white star <!-- source suggests B2V but may be too exact --> of around 10 solar masses.<ref>{{cite journal |last1=Peimbert |first1=M. |last2=Wallerstein | first2= G.| last3= Pilachowski | first3= C. A. |title=An upper limit for the deuterium abundance in Canopus |journal=Astronomy and Astrophysics |date=1981 |volume=104 |issue=1 |pages=72–74 | bibcode=1981A&A...104...72P}}</ref> The position of Canopus in the [[H–R diagram]] indicates that it is currently in the core-helium burning phase.<ref name=vlti/> It is an intermediate mass star that has left the [[red-giant branch]] before its core became [[degenerate matter|degenerate]] and is now in a [[blue loop]].<ref name=desouza>{{Cite journal | last1 = Domiciano De Souza | first1 = A. | last2 = Bendjoya | first2 = P. | last3 = Vakili | first3 = F. | last4 = Millour | first4 = F. | last5 = Petrov | first5 = R. G. | title = Diameter and photospheric structures of Canopus from AMBER/VLTI interferometry | doi = 10.1051/0004-6361:200810450 | journal = Astronomy and Astrophysics | volume = 489 | issue = 2 | pages = L5–L8 | year = 2008 |bibcode = 2008A&A...489L...5D | url = https://hal.archives-ouvertes.fr/hal-00316994/document | doi-access = free }}</ref> Models of stellar evolution in the blue loop phase show that the length of the blue loop is strongly affected by rotation and mixing effects inside the star. It is difficult to determine whether a star is currently evolving towards hotter temperature or returning to cooler temperatures, since the evolutionary tracks for stars with different masses overlap during the blue loops.<ref name=smiljanic2006>{{cite journal |bibcode=2006A&A...449..655S |title=CNO in evolved intermediate mass stars |last1=Smiljanic |first1=R. |last2=Barbuy |first2=B. |last3=De Medeiros |first3=J. R. |last4=Maeder |first4=A. |journal=Astronomy and Astrophysics |year=2006 |volume=449 |issue=2 |page=655 |doi=10.1051/0004-6361:20054377 |arxiv=astro-ph/0511329 |s2cid=3711409 }}</ref> Canopus lies on the warm side of the [[instability strip]] and does not pulsate like [[Cepheid variables]] of a similar luminosity.<ref name=ayres2011>{{cite journal |doi=10.1088/0004-637X/738/2/120 |title=The Curious Case of the Alpha Persei Corona: A Dwarf in Supergiant's Clothing? |year=2011 |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |volume=738 |issue=2 |page=120 |bibcode=2011ApJ...738..120A |doi-access=free }}</ref> However its atmosphere does appear to be unstable, showing strong signs of convection.<ref name=smiljanic2006/> Canopus may not be massive enough for its [[nuclear fusion|fusion]] chain to reach iron and trigger a core collapse and subsequent [[supernova]], instead eventually becoming a neon-oxygen [[white dwarf]].<ref name=Kalerstars/> ==Cultural significance == Canopus was known to the ancient Mesopotamians and given the name ''NUN-ki'' and represented the city of [[Eridu]] in the ''Three Stars Each'' [[Babylonian star catalogues]] and later [[MUL.APIN]] around 1100 BC.<ref>{{cite journal | last = Rogers | first = John H. | date = 1998 | title = Origins of the Ancient Constellations: I. The Mesopotamian Traditions | journal = Journal of the British Astronomical Association | volume = 108 | issue = 1 | pages = 9–28 | bibcode = 1998JBAA..108....9R}}</ref> Today, the star [[Sigma Sagittarii]] is known by the common name Nunki.<ref name=allen>{{citation | page=359 | first1=Richard Hinckley | last1=Allen | title=Star Names, their lore and meaning}}</ref> Canopus was not visible to the mainland [[Ancient Greece|ancient Greeks]] and [[Roman Empire|Romans]]; it was, however, visible to the [[ancient Egypt]]ians.<ref name="Schaaf107">Schaaf, p. 107.</ref> Hence [[Aratus]] did not write of the star as it remained below the horizon, while [[Eratosthenes]] and [[Ptolemy]]—observing from [[Alexandria]]—did, calling it ''Kanōbos''.<ref name=ridpathCr>{{cite web| url=http://www.ianridpath.com/startales/carina.htm | title=Carina |last1=Ridpath|first1=Ian|publisher=self-published |work=Star Tales | access-date= 10 December 2015}}</ref> An [[Egypt]]ian priestly poet in the time of [[Thutmose III]] mentions the star as ''Karbana,'' "the star which pours his light in a glance of fire, when he disperses the morning dew."<ref name="hinkley63" /> Under the [[Ptolemies]], the star was known as ''Ptolemaion'' ([[Ancient Greek|Greek]]: Πτολεμαῖον) and its [[acronychal rising]] marked the date of the Ptolemaia festival, which was held every four years, from 262 to 145 BC.<ref>[[Martianus Capella]] 7.838, {{cite journal | last1 = Hazzard | last2 = Fitzgerald | year = 1991 | title = The Regulation of the Ptolemeia | journal = Journal of the Royal Astronomical Society of Canada | volume = 85 | pages = 6–23 |bibcode = 1991JRASC..85....6H }}; Hazzard. 2000. ''Imagination of a Monarchy: Studies in Ptolemaic Propaganda'', 34–36.</ref> [[File:Statue of Averroes in Córdoba, Spain.jpg|thumb|upright|[[Averroes]], who used his 1153 observation of Canopus in [[Marrakesh]] while the star was invisible in his native Spain as an argument that the [[Spherical Earth|earth is round]].<ref name=ibn_rushd/>]] ===India=== In Indian [[Vedas|Vedic literature]], Canopus is associated with the sage [[Agastya]], one of the ancient [[siddhar]]s and [[rishi]]s (the others are associated with the stars of the [[Big Dipper]]).<ref name="Frawley 1993">{{cite book|last=Frawley|first=David|title=Gods, Sages and Kings: Vedic Secrets of Ancient Civilization|publisher=Motilal Banarsidass |location=New Delhi, India|date=1993}}</ref> To Agastya, the star is said to be the 'cleanser of waters', and its rising coincides with the calming of the waters of the [[Indian Ocean]]. It is thus considered the son of [[Pulastya]], son of [[Brahma]]. Canopus is described by [[Pliny the Elder]] and [[Gaius Julius Solinus]] as the largest, brightest and only source of [[starlight]] for navigators near [[Tamraparni]] island (ancient Sri Lanka) during many nights.<ref>{{cite book |last1=Pridham |first1=Charles |title=An Historical, Political, and Statistical Account of Ceylon and Its Dependencies |date=1849 |publisher=T. and W. Boone |page=7 |url=https://books.google.com/books?id=O4aqHOMSJdYC&pg=PR19-IA5|language=en}}</ref><ref name="Frawley 1993"/><ref>{{cite book |last1=Elder |first1=Pliny the |title=Delphi Complete Works of Pliny the Elder (Illustrated) |date=2015 |publisher=Delphi Classics |url=https://books.google.com/books?id=OrJ0CgAAQBAJ&pg=PA343|language=en}}</ref> ===China=== Canopus was described as Shou Xing, the Star of Longevity, in the ''Shiji'' ([[Records of the Grand Historian]]) completed in 94 BC by Chinese historian [[Sima Qian]].<ref name=fong83>{{cite journal | title=The Iconography of the Popular Gods of Happiness, Emolument, and Longevity (Fu Lu Shou) | first=Mary H. |last=Fong | journal=Artibus Asiae | volume= 44 | issue= 2/3 | year=1983| pages= 159–199 | doi= 10.2307/3249596| jstor=3249596 }}</ref> Drawing on sources from the [[Warring States period]], he noted it to be the southern counterpart of [[Sirius]],<ref name="IDP"/> and wrote of a sanctuary dedicated to it established by Emperor [[Qin Shi Huang]] between 221 and 210 BC. During the [[Han dynasty]], the star was auspicious, its appearance in the southern sky heralding peace and absence war.<ref name=fong83/> From the imperial capital [[Chang'an]], the star made a low transit across the southern sky, indicating true south to observers, and was often obscured by clouds.<ref name=baumann19>{{cite journal | title=The White Old Man: Géluk-Mongolian Canopus Allegory and the Existence of God | first=Brian | last=Baumann | journal= Central Asiatic Journal | volume= 62 | issue= 1 | year=2019| pages= 35–68 | doi=10.13173/centasiaj.62.1.0035| s2cid=213083544 }}</ref> During this time it was also equated with [[Old Man of the South Pole]] (in {{zh|c=南极老人|p=Nanji Lǎorén}})<ref name=fong83/> Under this name, Canopus appears (albeit misplaced northwards) on the medieval Chinese manuscript the [[Dunhuang Star Chart]], although it cannot be seen from the Chinese capital of [[Chang'an]].<ref name="IDP">{{cite journal|bibcode=2009JAHH...12...39B|arxiv=0906.3034|title=The Dunhuang Sky: A Comprehensive Study of the Oldest Known Star Atlas|volume=12|issue=1|pages=39–59|last1=Bonnet-Bidaud|first1=Jean-Marc |last2=Praderie|first2=Françoise |last3=Whitfield|first3=Susan |author-link=Susan Whitfield |journal=The International Dunhuang Project: The Silk Road Online|year=2009}}</ref> The Chinese astronomer [[Yi Xing]] had journeyed south to chart Canopus and other far southern stars in 724 AD.<ref>{{cite book|last=Needham|first=Joseph|title=Science and Civilisation in China: Volume 3, Mathematics and the Sciences of the Heavens and the Earth|publisher=Cambridge University Press|location=Cambridge, United Kingdom|date=1959|pages=274|isbn=0521058015}}</ref> Its personification as the Old Man Star was popularised in the [[Tang Dynasty]], where it appeared often in poetry and memorials. Later still, during the [[Ming Dynasty]], the star was established as one of the [[Sanxing (deities)|Three Stars]] (Fu Lo Shou), appearing frequently in art and literature of the time.<ref name=fong83/> This symbolism spread into neighbouring cultures in Asia.<ref name=baumann19/> In Japan, Canopus is known as ''Mera-boshi'' and ''Roujin-sei'' (the old man star),<ref>{{cite conference |url=http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |title=Stellar Iconology and Astronomical Folklore in Japan |author=Takao Ibaraki |book-title=International Planetarium Society (IPS) Conferences 1996 |publisher=International Planetarium Society |location=Osaka |date=14 July 1996 |access-date=25 February 2012 |url-status=dead |archive-url=https://web.archive.org/web/20120326195757/http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |archive-date=2012-03-26 }}</ref> and in Mongolia, it was personified as the White Old Man.<ref name=fong83/> Although the link was known in Tibet, with names such as ''Genpo karpo'' (''Rgan po dkar po'') or ''Genkar'' (''Rgan dkar'') "White Old Man", the symbolism was not popular. Instead, Canopus was more commonly named ''Karma Rishi སྐར་མ་རི་ཥི།'', derived from Indian mythology. Tibetans celebrated the star's heliacal rising with ritual bathing and associated it with morning dew.<ref name=baumann19/> ===Polynesia=== Bright stars were important to the ancient [[Polynesian culture|Polynesians]] for navigation between the many islands and atolls of the Pacific Ocean. Low on the horizon, they acted as stellar compasses to assist mariners in charting courses to particular destinations. Canopus served as the southern wingtip of a "Great Bird" constellation called ''Manu'', with Sirius as the body and [[Procyon]] the northern wingtip, which divided the Polynesian night sky into two hemispheres.<ref name="Holberg">{{cite book | last=Holberg | first=J.B. | title=Sirius: Brightest Diamond in the Night Sky | date=2007 | publisher=Praxis Publishing | location=Chichester, UK | isbn=978-0-387-48941-4 | pages=[https://archive.org/details/siriusbrightestd0000holb/page/25 25–26] | url=https://archive.org/details/siriusbrightestd0000holb/page/25 }}</ref> The [[Hawaiian people]] called Canopus ''Ke Alii-o-kona-i-ka-lewa'', "The chief of the southern expanse"; it was one of the stars used by [[Hawaiʻiloa]] and Ki when they traveled to the [[Southern Ocean]].{{sfn|Makemson|1941|p=198}} The [[Māori people]] of [[New Zealand|New Zealand/Aotearoa]] had several names for Canopus. ''[[Ariki]]'' ("High-born"), was known as a solitary star that appeared in the east, prompting people to weep and chant.{{sfn|Makemson|1941|p=201}} They also named it ''[[Atutahi]]'', ''Aotahi'' or ''Atuatahi'', "Stand Alone".<ref>p. 419, [https://books.google.com/books?id=p7dR2w1Wv2sC ''Mythology: Myths, Legends and Fantasies''], Janet Parker, Alice Mills, Julie Stanton, Durban, Struik Publishers, 2007.</ref> Its solitary nature indicates it is a ''[[Tapu (Polynesian culture)|tapu]]'' star, as ''tapu'' people are often solitary. Its appearance at the beginning of the ''Maruaroa'' season foretells the coming winter; light rays to the south indicate a cold wet winter, and to the north foretell a mild winter. Food was offered to the star on its appearance.<ref name="Best22">{{cite book|last=Best|first=Elsdon|title=Astronomical Knowledge of the Maori: Genuine and Empirical|publisher=Dominion Museum|location=Wellington, New Zealand|date=1922|pages=34–35|url=http://nzetc.victoria.ac.nz/tm/scholarly/tei-BesAstro-t1-body-d1-d6-d4.html}}</ref> This name has several mythologies attached to it. One story tells of how Atutahi was left outside the basket representing the [[Milky Way]] when [[Tāne]] wove it. Another related myth about the star says that Atutahi was the first-born child of [[Rangi and Papa|Rangi]], who refused to enter the Milky Way and so turned it sideways and rose before it. The same name is used for other stars and constellations throughout Polynesia.{{sfn|Makemson|1941|pp=200–202}} ''Kapae-poto'', "Short horizon", referred to it rarely setting as seen in New Zealand;{{sfn|Makemson|1941|p=217}} ''Kauanga'' ("Solitary") was the name for Canopus only when it was the last star visible before sunrise.{{sfn|Makemson|1941|p=218}} The people of the [[Society Islands]] had two names for Canopus, as did the [[Tuamotu]] people. The Society Islanders called Canopus ''Taurua-e-tupu-tai-nanu'', "Festivity-whence-comes-the-flux-of-the-sea", and ''Taurua-nui-o-te-hiti-apatoa'' "Great-festivity-of-the-border-of-the-south",{{sfn|Makemson|1941|p=259}} and the Tuamotu people called the star ''Te Tau-rari'' and ''Marere-te-tavahi'', the latter said to be the true name for the former, "He-who-stands-alone".{{sfn|Makemson|1941|p=229}} ===Africa=== In the [[Guanches|Guanche]] mythology of the island of [[Tenerife]] (Spain), the star Canopus was linked with the goddess [[Chaxiraxi]].<ref name="Rumeu">{{cite book|author=Antonio Rumeu de Armas|title=La conquista de Tenerife, 1494–1496|url=https://books.google.com/books?id=Ck4BAAAAMAAJ|year=1975|publisher=Aula de Cultura de Tenerife|isbn=9788450071078}}</ref> The [[Tswana people]] of [[Botswana]] knew Canopus as ''Naka''. Appearing late in winter skies, it heralded increasing winds and a time when trees lose their leaves. Stock owners knew it was time to put their sheep with rams.<ref>{{cite journal|last=Clegg|first=Andrew|date=1986|title=Some Aspects of Tswana Cosmology|journal=Botswana Notes and Records|volume=18|pages=33–37|jstor=40979758 }}</ref> In southern Africa, the Sotho, Tswana and Venda people called Canopus ''Naka'' or ''Nanga'', “the Horn Star”, while the Zulu and Swazi called it ''inKhwenkwezi'' "Brilliant star". It appears in the predawn sky in the third week of May. According to the Venda, the first person to see Canopus would blow a ''phalaphala'' horn from the top of a hill, getting a cow for a reward. The Sotho chiefs also awarded a cow, and ordered their medicine men to roll bone dice and read the fortune for the coming year.<ref name=snedegar95>{{cite journal |last1=Snedegar |first1=K.V. |title=Stars and seasons in Southern Africa |journal=Vistas in Astronomy |date=1995 |volume=39 |issue=4 |pages=529–38 |doi=10.1016/0083-6656(95)00008-9|bibcode=1995VA.....39..529S }}</ref> To the [[ǀXam language|ǀXam]]-speaking [[Bushmen]] of South Africa, Canopus and Sirius signalled the appearance of termites and flying ants. They also believed that stars had the power to cause death and misfortune, and they would pray to [[Sirius]] and Canopus in particular to impart good fortune or skill.<ref>{{cite journal| title="The Sky's Things", <nowiki>|</nowiki>xam Bushman 'Astrological Mythology' as recorded in the Bleek and Lloyd Manuscripts |last1=Hollman|first1=J. C.|journal=African Sky|volume= 11|page=8 |bibcode=2007AfrSk..11....8H|year = 2007 }}</ref> The [[ǃKung people]] of the [[Kalahari Desert]] in Botswana held Canopus and Capella to be the horns of ''tshxum'' (the Pleiades), the appearance of all three marking the end of the dry season and start of the rainy season.<ref>{{cite journal |last1=Marshall |first1=Lorna |title=Two Ju/ wa constellations |journal=Botswana Notes & Records |date=1975 |volume=7 |issue=1 |pages=153–159 | issn=0525-5090 |url=https://journals.co.za/docserver/fulltext/botnotes/7/1/548.pdf?expires=1590793041&id=id&accname=guest&checksum=3204085F9555AD9D083799E1F38E3AED}}</ref> ===Americas=== The [[Navajo]] observed the star and named it ''Maʼii Bizòʼ'', the “Coyote Star”. According to legend, Maʼii (Coyote) took part in the naming and placing of the star constellations during the creation of the universe. He placed Canopus directly south, naming it after himself.<ref name="Maryboy">Maryboy, Nancy D. (2004). ''A Guide to Navajo Astronomy.'' Indigenous Education Institute : Bluff, Utah.</ref> The [[Kalapalo]] people of [[Mato Grosso]] state in Brazil saw Canopus and [[Procyon]] as ''Kofongo'' "Duck", with [[Castor (star)|Castor]] and [[Pollux (star)|Pollux]] representing his hands. The asterism's appearance signified the coming of the rainy season and increase in [[manioc]], a food staple fed to guests at feasts.<ref name="basso87">{{cite book|last=Basso|first=Ellen B. |title=In Favor of Deceit: A Study of Tricksters in an Amazonian Society|publisher=University of Arizona Press|location=Tucson, Arizona|date=1987|page=[https://archive.org/details/infavorofdeceits0000bass/page/360 360]|isbn=0816510229|url=https://archive.org/details/infavorofdeceits0000bass|url-access=registration}}</ref> ===Australia=== Canopus is identified as the moiety ancestor ''Waa'' "Crow" to some [[Koori]] people in southeastern Australia.<ref>{{cite book|last=Mudrooroo|title=Aboriginal mythology: an A-Z spanning the history of aboriginal mythology from the earliest legends to the present day|publisher=HarperCollins|location=London|date=1994|page=27|isbn=1-85538-306-3}}</ref> The Boorong people of northwestern Victoria recalled that ''War'' (Canopus) was the brother of ''Warepil'' (Sirius), and that he brought fire from the heavens and introduced it to humanity. His wife was ''Collowgullouric War'' ([[Eta Carinae]]).<ref name=hamacher10>{{cite journal|last1=Hamacher|first1=Duane W. |last2=Frew|first2=David J. |date=2010|title= An Aboriginal Australian Record of the Great Eruption of Eta Carinae|journal=Journal of Astronomical History & Heritage |volume=13|issue=3|pages= 220–34|bibcode=2010JAHH...13..220H|arxiv = 1010.4610 }}</ref> The Pirt-Kopan-noot people of western Victoria tell of ''Waa'' "Crow" falling in love with a queen, ''Gneeanggar'' "Wedge-tailed Eagle" (Sirius) and her six attendants (the Pleiades). His advances spurned, he hears that the women are foraging for grubs and so transforms himself into a grub. When the women dig him out, he changes into a giant and carries her off.<ref>Mudroodoo, p. 55.</ref> The Kulin people know Canopus as ''Lo-an-tuka''.<ref name=hamacher10/> Objects in the sky are also associated with states of being for some tribes; the Wailwun of northern New South Wales know Canopus as ''Wumba'' "deaf", alongside Mars as ''Gumba'' "fat" and Venus as ''Ngindigindoer'' "you are laughing".<ref name="noctuary">{{cite book|last=Johnson|first=Diane|title=Night skies of aboriginal Australia: a noctuary|publisher=University of Sydney|location=Darlington, New South Wales|date=1998|page=[https://archive.org/details/nightskiesofabor0000john/page/84 84]|isbn=1-86451-356-X|url-access=registration|url=https://archive.org/details/nightskiesofabor0000john/page/84}}</ref> Tasmanian aboriginal lore holds that Canopus is ''Dromerdene'', the brother of ''Moinee''; the two fought and fell out of the sky, with ''Dromerdene'' falling into Louisa Bay in southwest Tasmania.<ref name="haynes2000">{{cite book|last=Haynes|first=Ros D.|title= Astronomy and the Dreaming: The Astronomy of the Aboriginal Australians. Astronomy Across Cultures: The History of Non-Western Astronomy|publisher=Kluwer Academic Publishers|date=2000|page=57|doi=10.1007/978-94-011-4179-6_3}}</ref> ===Legacy=== [[File:HMS Glory LOC ggbain.17135.jpg|thumb|right|[[Canopus-class battleship]] HMS Glory]] Canopus appears on the [[flag of Brazil]], symbolising the state of [[Goiás]].<ref>{{cite web |title=Astronomy of the Brazilian Flag |url=https://flagspot.net/flags/br_astro.html |publisher=FOTW Flags Of The World website }}</ref> Two U.S. Navy [[submarine tender]]s have been named after Canopus, the [[USS Canopus (AS-9)|first]] serving from 1922 to 1942 and the [[USS Canopus (AS-34)|second]] serving from 1965 to 1994. The [[Royal Navy]] built nine [[Canopus-class ship of the line|Canopus-class ships of the line]] in the early 19th century, and six {{Sclass|Canopus|battleship|1}}s which entered services between 1899 and 1902. There are at least two mountains named after the star: [[Mount Canopus]] in Antarctica; and Mount Canopus or Canopus Hill in [[Tasmania]], the location of the [[Canopus Hill Observatory|Canopus Hill astronomical observatory]]. {{clear}} ==See also== *[[List of brightest stars]] *[[List of most luminous stars]] *[[Dune (novel)]] ==References== {{Reflist|30em}} ===Bibliography=== * {{cite book | last = Makemson | first = Maud Worcester | date = 1941 | publisher = [[Yale University Press]] | title = The Morning Star Rises: an account of Polynesian astronomy | bibcode = 1941msra.book.....M }} * {{cite book |title=The Brightest Stars: Discovering the Universe through the Sky's Most Brilliant Stars |last=Schaaf |first=Fred |year=2008 |publisher=John Wiley & Sons |location=Hoboken, NJ |isbn=978-0-471-70410-2 }} == External links == {{Sky|06|23|57.1099|-|52|41|44.378|310}} {{Carina (constellation)}} {{Portal bar|Astronomy|Stars|Spaceflight|Outer space|Solar System}} {{Authority control}} {{DEFAULTSORT:Canopus}} [[Category:Canopus| ]] [[Category:Bayer objects|Carinae, Alpha]] [[Category:Carina (constellation)]] [[Category:A-type bright giants]] [[Category:Henry Draper Catalogue objects|045348]] [[Category:Hipparcos objects|030438]] [[Category:Bright Star Catalogue objects|2326]] [[Category:Stars with proper names]] [[Category:Durchmusterung objects]] 3547233edddd3de1b6a9882514b6f145cc63ca57 Module:Val/units 828 45 105 2022-09-01T19:37:59Z Canopus >BD2412 0 KB [[Kilobyte|KB]] 8e3 Scribunto text/plain -- Definitions for units known to val -- File format is two strings and a return statement with them in it: -- string in quotes [=[ ... builtin_units ... ]=]. -- string in quotes [=[ ... builtin_units_long_scale ... ]=]. -- First string, builtin_units, is short-scale, second string is long scale. -- Entry format: -- One record per line, starting in first column, having 2-4 fields. -- Field separator: two or more spaces -- Between first and second fields: two or more spaces -- Between all other fields: two or more spaces, or one or more tabs -- Entries without two spaces in them are ignored. -- There must be a blank line before the first entry and after the last. -- I.e. the first two and last two characters of the string must be newlines. -- Format of entry. Two record types: -- -- One record type is a wikilink: -- Unit-code [[ pagename | Symbol-accepts-HTML-only ]] -- Text-field separator is still two spaces. Two spaces not allowed in wikilink. -- -- The other record type is all fields: -- Unit-code symbol-accepts-HTML-only pagename#section-OK -- -- Plus there is an optional field that goes at the end after two or more spaces. -- Whether it is a number or an equation or the letters SI, -- any of these three has the same function: a wikitable sorting "scale". -- It is for sorting, and it works for either record type. -- Difference is SI can't accept HTML. But SI correctly scales any SI prefix. -- (Optional fields ALIAS and NOSPACE and ANGLE are for advanced users.) -- "Invalid unit" error: -- Using SI requires that the symbol equal unit-code, so never allows HTML. -- Any difference between SI or symbol must be an SI prefix, such as k, M, or G. -- A space at the end of an entry is an error. No space at each EOL. local builtin_units = [=[ == Test == Foo [[Hz|<samp>Foo</samp>]] Baz [[Hertz|baz<sub>0</sub>]] Baz [[Kelvins|baz<sub>0</sub>]] Bar [[Foobar|bar<abbr title="super duper">0</abbr>]] quux [[Foobar|<span title="super duper 2">bar0</span>]] == Unsorted units == c0 [[Speed of light#Numerical value, notation, and units|''c''<sub>0</sub>]] lbf [[Pound (force)|<span title="pound-force">lb<sub>F</sub></span> ]] N.s [[Newton-second|N&sdot;s]] J.K-1 [[Joule per kelvin|J&sdot;K<sup>−1</sup>]] C.mol-1 [[Faraday constant|C&sdot;mol<sup>−1</sup>]] C/mol [[Faraday constant|C/mol]] C.kg-1 [[Roentgen (unit)|C&sdot;kg<sup>−1</sup>]] C/kg [[Roentgen (unit)|C/kg]] F.m-1 [[vacuum permittivity|F&sdot;m<sup>−1</sup>]] F/m [[vacuum permittivity|F/m]] e [[Elementary charge|''e'']] kB [[Kilobyte|kB]] 8e3 KB [[Kilobyte|KB]] 8e3 MB [[Megabyte|MB]] 8e6 GB [[Gigabyte|GB]] 8e9 TB [[Terabyte|TB]] 8e12 lx [[Lux (unit)|lx]] nat [[nat (unit)|nat]] == Time and frequency == byte/s [[Data rate units|byte/s]] 8 kB/s [[Data rate units#Kilobyte per second|<span title="Kilobytes per second">kB/s</span>]] 8e3 MB/s [[Data rate units#Megabyte per second|<span title="Megabytes per second">MB/s</span>]] 8e6 GB/s [[Data rate units#Gigabyte per second|<span title="Gigabytes per second">GB/s</span>]] 8e9 TB/s [[Data rate units#Terabyte per second|<span title="Terabytes per second">TB/s</span>]] 8e12 bit/s [[Bit per second|bit/s]] 1 bps [[Bit per second|bit/s]] 1 kbit/s [[Kilobit per second|kbit/s]] 1e3 Mbit/s [[Megabit per second|Mbit/s]] 1e6 Gbit/s [[Gigabit per second|Gbit/s]] 1e9 Tbit/s [[Terabit per second|Tbit/s]] 1e12 kT/s [[Transfer (computing)|<span title="Kilotransfers per second">kT/s</span>]] 1e3 MT/s [[Transfer (computing)|<span title="Megatransfers per second">MT/s</span>]] 1e6 GT/s [[Transfer (computing)|<span title="Gigatransfers per second">GT/s</span>]] 1e9 year [[Year|year]] 31557600 years [[Year|years]] 31557600 yr [[Year#Symbols y and yr|yr]] 31557600 y [[Year|y]] 31557600 a [[Annum|a]] 31557600 Ga [[Gigaannum|Ga]] 31557600000000000 Ma [[Megaannum|Ma]] 31557600000000 ka [[Kiloannum|ka]] 31557600000 kyr [[kyr|kyr]] 31557600000 kya [[kyr|kya]] 31557600000 myr [[myr|myr]] 31557600000000 mya [[Mya (unit)|mya]] 31557600000000 byr [[Billion years|byr]] 31557600000000000 bya [[Billion years ago|bya]] 31557600000000000 Gyr [[billion years|Gyr]] 31557600000000000 BP [[Before present|BP]] uBP [[Radiocarbon dating#Calibration|<sup>14</sup>C yr BP]] BC [[Before Christ|BC]] -1 AD [[Anno Domini|AD]] 1 BCE [[Before the Common Era|BCE]] -1 CE [[Common Era|CE]] 1 JD [[Julian date|JD]] 1 MJD [[Modified Julian date|MJD]] 1 s-1 [[Second|s<sup>−1</sup>]] s-2 [[Second|s<sup>−2</sup>]] s2 [[Second|s<sup>2</sup>]] s [[Second|s]] SI as [[Attosecond|s]] SI cs [[Second|s]] SI das [[Second|s]] SI ds [[Second|s]] SI Es [[Second|s]] SI fs [[Femtosecond|s]] SI Gs [[Second|s]] SI hs [[Second|s]] SI ks [[Second|s]] SI ms [[Millisecond|s]] SI µs [[Microsecond|s]] SI us [[Microsecond|s]] SI Ms [[Second|s]] SI ns [[Nanosecond|s]] SI ps [[Picosecond|s]] SI Ps [[Second|s]] SI Ts [[Second|s]] SI Ys [[Second|s]] SI ys [[Yoctosecond|s]] SI Zs [[Second|s]] SI zs [[Zeptosecond|s]] SI Hz [[Hertz|Hz]] SI aHz [[Hertz|Hz]] SI cHz [[Hertz|Hz]] SI daHz [[Hertz|Hz]] SI dHz [[Hertz|Hz]] SI EHz [[Hertz|Hz]] SI fHz [[Hertz|Hz]] SI hHz [[Hertz|Hz]] SI GHz [[Gigahertz|Hz]] SI kHz [[Kilohertz|Hz]] SI MHz [[Megahertz|Hz]] SI mHz [[Hertz|Hz]] SI uHz [[Hertz|Hz]] SI µHz [[Hertz|Hz]] SI nHz [[Hertz|Hz]] SI pHz [[Hertz|Hz]] SI PHz [[Hertz|Hz]] SI THz [[Hertz|Hz]] SI yHz [[Hertz|Hz]] SI YHz [[Hertz|Hz]] SI zHz [[Hertz|Hz]] SI ZHz [[Hertz|Hz]] SI ips [[Inch per second|ips]] == Length, area, volume == Å3 [[Ångström|Å<sup>3</sup>]] fb-1 [[Barn (unit)|fb<sup>−1</sup>]] m-1 [[Metre|m<sup>−1</sup>]] m-2 [[Square metre|m<sup>−2</sup>]] m-3 [[Cubic metre|m<sup>−3</sup>]] km2 [[Square kilometre|km<sup>2</sup>]] km3 [[Cubic kilometre|km<sup>3</sup>]] µm2 [[Square metre|µm<sup>2</sup>]] um2 [[Square metre|µm<sup>2</sup>]] am2 [[Square metre|am<sup>2</sup>]] cm2 [[Square centimetre|cm<sup>2</sup>]] dam2 [[Square metre|dam<sup>2</sup>]] dm2 [[Square metre|dm<sup>2</sup>]] Em2 [[Square metre|Em<sup>2</sup>]] fm2 [[Square metre|fm<sup>2</sup>]] Gm2 [[Square metre|Gm<sup>2</sup>]] hm2 [[Square metre|hm<sup>2</sup>]] mm2 [[Square metre|mm<sup>2</sup>]] Mm2 [[Square metre|Mm<sup>2</sup>]] nm2 [[Square metre|nm<sup>2</sup>]] pm2 [[Square metre|pm<sup>2</sup>]] Pm2 [[Square metre|Pm<sup>2</sup>]] Tm2 [[Square metre|Tm<sup>2</sup>]] ym2 [[Square metre|ym<sup>2</sup>]] Ym2 [[Square metre|Ym<sup>2</sup>]] zm2 [[Square metre|zm<sup>2</sup>]] Zm2 [[Square metre|Zm<sup>2</sup>]] gal [[Gallon|gal]] Gal [[Gal (unit)|Gal]] uGal [[Gal (unit)|µGal]] µGal [[Gal (unit)|µGal]] mGal [[Gal (unit)|mGal]] b [[Barn (unit)|b]] SI ab [[Barn (unit)|b]] SI cb [[Barn (unit)|b]] SI dab [[Barn (unit)|b]] SI db [[Barn (unit)|b]] SI Eb [[Barn (unit)|b]] SI fb [[Barn (unit)|b]] SI Gb [[Barn (unit)|b]] SI hb [[Barn (unit)|b]] SI kb [[Barn (unit)|b]] SI mb [[Barn (unit)|b]] SI µb [[Barn (unit)|b]] SI ub [[Barn (unit)|b]] SI Mb [[Barn (unit)|b]] SI nb [[Barn (unit)|b]] SI pb [[Barn (unit)|b]] SI Pb [[Barn (unit)|b]] SI Tb [[Barn (unit)|b]] SI Yb [[Barn (unit)|b]] SI yb [[Barn (unit)|b]] SI Zb [[Barn (unit)|b]] SI zb [[Barn (unit)|b]] SI == Velocity and acceleration == m.s-2 [[Metre per second squared|m&sdot;s<sup>−2</sup>]] m/s2 [[Metre per second squared|m/s<sup>2</sup>]] m.s-1 [[Metre per second|m&sdot;s<sup>−1</sup>]] m/s [[Metre per second|m/s]] km.s-1 [[Metre per second|km&sdot;s<sup>−1</sup>]] km/s [[Metre per second|km/s]] == Mass and energy == lbm [[Pound (mass)|<span title="pound-mass">lb<sub>m</sub></span>]] uJ [[Joule|µJ]] J.s [[Joule-second|J&sdot;s]] kWh [[Kilowatt hour|kWh]] kW.h [[Kilowatt hour|kW&sdot;h]] J/C [[Volt|J/C]] J/kg [[Joule|J/kg]] Da [[Dalton (unit)|Da]] SI EDa [[Dalton (unit)|Da]] SI PDa [[Dalton (unit)|Da]] SI TDa [[Dalton (unit)|Da]] SI GDa [[Dalton (unit)|Da]] SI MDa [[Dalton (unit)|Da]] SI kDa [[Dalton (unit)|Da]] SI mDa [[Dalton (unit)|Da]] SI uDa [[Dalton (unit)|Da]] SI μDa [[Dalton (unit)|Da]] SI nDa [[Dalton (unit)|Da]] SI pDa [[Dalton (unit)|Da]] SI fDa [[Dalton (unit)|Da]] SI aDa [[Dalton (unit)|Da]] SI g [[Gram|g]] SI ag [[Attogram|g]] SI cg [[Centigram|g]] SI dag [[Gram|g]] SI dg [[Decigram|g]] SI Eg [[Exagram|g]] SI fg [[Femtogram|g]] SI Gg [[Gigagram|g]] SI hg [[Kilogram#SI multiples|g]] SI kg [[Kilogram|g]] SI mcg [[Microgram|g]] SI Mg [[Megagram|g]] SI mg [[Milligram|g]] SI ug [[Microgram|g]] SI µg [[Microgram|g]] SI ng [[Nanogram|g]] SI Pg [[Petagram|g]] SI pg [[Picogram|g]] SI Tg [[Tonne|g]] SI yg [[Yoctogram|g]] SI Yg [[Yottagram|g]] SI zg [[Zeptogram|g]] SI Zg [[Zettagram|g]] SI == Pressure and density == psi [[Pounds per square inch|psi]] g.cm-3 [[Gram per cubic centimetre|g&sdot;cm<sup>−3</sup>]] g/cm3 [[Gram per cubic centimetre|g/cm<sup>3</sup>]] kg.m-3 [[Kilogram per cubic metre|kg&sdot;m<sup>−3</sup>]] kg/m3 [[Kilogram per cubic metre|kg/m<sup>3</sup>]] kg/cm3 [[Density#Formula and common units|kg/cm<sup>3</sup>]] g/L [[Gram per litre|g/L]] g/l [[Gram per litre|g/l]] mcg/dL [[Gram per litre|µg/dL]] mcg/dl [[Gram per litre|µg/dl]] mg/mL [[Gram per litre|mg/mL]] mg/ml [[Gram per litre|mg/ml]] ug/dL [[Gram per litre|µg/dL]] ug/dl [[Gram per litre|µg/dl]] μg/dL [[Gram per litre|μg/dL]] μg/dl [[Gram per litre|μg/dl]] mg.L-1 [[Gram per litre|<abbr title="milligrams per liter">mg/L</abbr>]] mg/L [[Gram per litre|<abbr title="milligrams per liter">mg/L</abbr>]] mg.l-1 [[Gram per litre|<abbr title="milligrams per liter">mg/l</abbr>]] mg/l [[Gram per litre|<abbr title="milligrams per liter">mg/l</abbr>]] == Fracture toughness == MPa.m.5 [[Fracture toughness|MPa&sdot;m<sup>1/2</sup>]] kPa.m.5 [[Fracture toughness|kPa&sdot;m<sup>1/2</sup>]] Pa.m.5 [[Fracture toughness|Pa&sdot;m<sup>1/2</sup>]] == Temperature == degC °C ALIAS degF °F ALIAS degR °R ALIAS K [[Kelvin|K]] SI YK [[Yottakelvin|K]] SI ZK [[Zettakelvin|K]] SI EK [[Kelvin|K]] SI PK [[Petakelvin|K]] SI TK [[Terakelvin|K]] SI GK [[Gigakelvin|K]] SI MK [[Megakelvin|K]] SI kK [[Kilokelvin|K]] SI hK [[Hectokelvin|K]] SI daK [[Decakelvin|K]] SI dK [[Decikelvin|K]] SI cK [[Centikelvin|K]] SI mK [[Millikelvin|K]] SI µK [[Microkelvin|K]] SI uK [[Microkelvin|K]] SI nK [[Nanokelvin|K]] SI pK [[Picokelvin|K]] SI fK [[Femtokelvin|K]] SI aK [[Attokelvin|K]] SI zK [[Zeptokelvin|K]] SI yK [[Yoctokelvin|K]] SI == Electromagnetism == Wb [[Weber (unit)|Wb]] N.A-2 [[Permeability (electromagnetism)|N&sdot;A<sup>−2</sup>]] H.m-1 [[Permeability (electromagnetism)|H&sdot;m<sup>−1</sup>]] V.m-1 [[Electric field|V&sdot;m<sup>−1</sup>]] V/m [[Electric field|V/m]] C [[Coulomb|C]] SI YC [[Coulomb|C]] SI ZC [[Coulomb|C]] SI EC [[Coulomb|C]] SI PC [[Coulomb|C]] SI TC [[Coulomb|C]] SI GC [[Coulomb|C]] SI MC [[Coulomb|C]] SI kC [[Coulomb|C]] SI hC [[Coulomb|C]] SI daC [[Coulomb|C]] SI dC [[Coulomb|C]] SI cC [[Coulomb|C]] SI mC [[Coulomb|C]] SI µC [[Coulomb|C]] SI uC [[Coulomb|C]] SI nC [[Coulomb|C]] SI pC [[Coulomb|C]] SI fC [[Coulomb|C]] SI aC [[Coulomb|C]] SI zC [[Coulomb|C]] SI yC [[Coulomb|C]] SI F [[Farad|F]] SI YF [[Farad|F]] SI ZF [[Farad|F]] SI EF [[Farad|F]] SI PF [[Farad|F]] SI TF [[Farad|F]] SI GF [[Farad|F]] SI MF [[Farad|F]] SI kF [[Farad|F]] SI hF [[Farad|F]] SI daF [[Farad|F]] SI dF [[Farad|F]] SI cF [[Farad|F]] SI mF [[Farad|F]] SI µF [[Farad|F]] SI uF [[Farad|F]] SI nF [[Farad|F]] SI pF [[Farad|F]] SI fF [[Farad|F]] SI aF [[Farad|F]] SI zF [[Farad|F]] SI yF [[Farad|F]] SI H [[Henry (unit)|H]] SI YH [[Henry (unit)|H]] SI ZH [[Henry (unit)|H]] SI EH [[Henry (unit)|H]] SI PH [[Henry (unit)|H]] SI TH [[Henry (unit)|H]] SI GH [[Henry (unit)|H]] SI MH [[Henry (unit)|H]] SI kH [[Henry (unit)|H]] SI hH [[Henry (unit)|H]] SI daH [[Henry (unit)|H]] SI dH [[Henry (unit)|H]] SI cH [[Henry (unit)|H]] SI mH [[Henry (unit)|H]] SI µH [[Henry (unit)|H]] SI uH [[Henry (unit)|H]] SI nH [[Henry (unit)|H]] SI pH [[Henry (unit)|H]] SI fH [[Henry (unit)|H]] SI aH [[Henry (unit)|H]] SI zH [[Henry (unit)|H]] SI yH [[Henry (unit)|H]] SI A [[Ampere|A]] SI YA [[Ampere|A]] SI ZA [[Ampere|A]] SI EA [[Ampere|A]] SI PA [[Ampere|A]] SI TA [[Ampere|A]] SI GA [[Ampere|A]] SI MA [[Ampere|A]] SI kA [[Ampere|A]] SI hA [[Ampere|A]] SI daA [[Ampere|A]] SI dA [[Ampere|A]] SI cA [[Ampere|A]] SI mA [[Ampere|A]] SI µA [[Ampere|A]] SI uA [[Ampere|A]] SI nA [[Ampere|A]] SI pA [[Ampere|A]] SI fA [[Ampere|A]] SI aA [[Ampere|A]] SI zA [[Ampere|A]] SI yA [[Ampere|A]] SI V [[Volt|V]] SI YV [[Volt|V]] SI ZV [[Volt|V]] SI EV [[Volt|V]] SI PV [[Volt|V]] SI TV [[Volt|V]] SI GV [[Volt|V]] SI MV [[Volt|V]] SI kV [[Volt|V]] SI hV [[Volt|V]] SI daV [[Volt|V]] SI dV [[Volt|V]] SI cV [[Volt|V]] SI mV [[Volt|V]] SI µV [[Volt|V]] SI uV [[Volt|V]] SI nV [[Volt|V]] SI pV [[Volt|V]] SI fV [[Volt|V]] SI aV [[Volt|V]] SI zV [[Volt|V]] SI yV [[Volt|V]] SI VA [[Volt-ampere|VA]] SI YVA [[Volt-ampere|VA]] SI ZVA [[Volt-ampere|VA]] SI EVA [[Volt-ampere|VA]] SI PVA [[Volt-ampere|VA]] SI TVA [[Volt-ampere|VA]] SI GVA [[Volt-ampere|VA]] SI MVA [[Volt-ampere|VA]] SI kVA [[Volt-ampere|VA]] SI hVA [[Volt-ampere|VA]] SI daVA [[Volt-ampere|VA]] SI dVA [[Volt-ampere|VA]] SI cVA [[Volt-ampere|VA]] SI mVA [[Volt-ampere|VA]] SI µVA [[Volt-ampere|VA]] SI uVA [[Volt-ampere|VA]] SI nVA [[Volt-ampere|VA]] SI pVA [[Volt-ampere|VA]] SI fVA [[Volt-ampere|VA]] SI aVA [[Volt-ampere|VA]] SI zVA [[Volt-ampere|VA]] SI yVA [[Volt-ampere|VA]] SI Ω [[Ohm|Ω]] SI YΩ.m [[Electrical resistivity and conductivity#Definition|YΩ&sdot;m]] 1e24 ZΩ.m [[Electrical resistivity and conductivity#Definition|ZΩ&sdot;m]] 1e21 EΩ.m [[Electrical resistivity and conductivity#Definition|EΩ&sdot;m]] 1e18 PΩ.m [[Electrical resistivity and conductivity#Definition|PΩ&sdot;m]] 1e15 TΩ.m [[Electrical resistivity and conductivity#Definition|TΩ&sdot;m]] 1e12 GΩ.m [[Electrical resistivity and conductivity#Definition|GΩ&sdot;m]] 1e9 MΩ.m [[Electrical resistivity and conductivity#Definition|MΩ&sdot;m]] 1e6 kΩ.m [[Electrical resistivity and conductivity#Definition|kΩ&sdot;m]] 1e3 Ω.m [[Electrical resistivity and conductivity#Definition|Ω&sdot;m]] 1 mΩ.m [[Electrical resistivity and conductivity#Definition|mΩ&sdot;m]] 1e-3 µΩ.m [[Electrical resistivity and conductivity#Definition|µΩ&sdot;m]] 1e-6 uΩ.m [[Electrical resistivity and conductivity#Definition|µΩ&sdot;m]] 1e-6 nΩ.m [[Electrical resistivity and conductivity#Definition|nΩ&sdot;m]] 1e-9 pΩ.m [[Electrical resistivity and conductivity#Definition|pΩ&sdot;m]] 1e-12 fΩ.m [[Electrical resistivity and conductivity#Definition|fΩ&sdot;m]] 1e-15 aΩ.m [[Electrical resistivity and conductivity#Definition|aΩ&sdot;m]] 1e-18 zΩ.m [[Electrical resistivity and conductivity#Definition|zΩ&sdot;m]] 1e-21 yΩ.m [[Electrical resistivity and conductivity#Definition|yΩ&sdot;m]] 1e-24 R [[Rayleigh (unit)|R]] SI G [[Gauss (unit)|G]] SI aG [[Attogauss|G]] SI cG [[Centigauss|G]] SI daG [[Decagauss|G]] SI dG [[Decigauss|G]] SI EG [[Exagauss|G]] SI fG [[Femtogauss|G]] SI GG [[Gigagauss|G]] SI hG [[Hectogauss|G]] SI kG [[Kilogauss|G]] SI MG [[Megagauss|G]] SI mG [[Milligauss|G]] SI uG [[Microgauss|G]] SI µG [[Microgauss|G]] SI nG [[Nanogauss|G]] SI PG [[Petagauss|G]] SI pG [[Picogauss|G]] SI TG [[Teragauss|G]] SI yG [[Yoctogauss|G]] SI YG [[Yottagauss|G]] SI zG [[Zeptogauss|G]] SI ZG [[Zettagauss|G]] SI T [[Tesla (unit)|T]] SI aT [[Attotesla|T]] SI cT [[Centitesla|T]] SI daT [[Decatesla|T]] SI dT [[Decitesla|T]] SI ET [[Exatesla|T]] SI fT [[Femtotesla|T]] SI GT [[Gigatesla|T]] SI hT [[Hectotesla|T]] SI kT [[Kilotesla|T]] SI MT [[Megatesla|T]] SI mT [[Millitesla|T]] SI uT [[Microtesla|T]] SI µT [[Microtesla|T]] SI nT [[Nanotesla|T]] SI PT [[Petatesla|T]] SI pT [[Picotesla|T]] SI TT [[Teratesla|T]] SI yT [[Yoctotesla|T]] SI YT [[Yottatesla|T]] SI zT [[Zeptotesla|T]] SI ZT [[Zettatesla|T]] SI == Astrophysics == au [[Astronomical unit|au]] c [[Speed of light|''c'']] ly [[Light-year|ly]] dex [[decimal exponent|dex]] Earth mass [[Earth mass|''M''<sub>🜨</sub>]] Earth radius [[Earth radius|''R''<sub>🜨</sub>]] M_Earth [[Earth mass|''M''<sub>🜨</sub>]] R_Earth [[Earth radius|''R''<sub>🜨</sub>]] M+ [[Earth mass|''M''<sub>🜨</sub>]] R+ [[Earth radius|''R''<sub>🜨</sub>]] Jupiter mass [[Jupiter mass|''M''<sub>J</sub>]] Jupiter radius [[Jupiter radius|''R''<sub>J</sub>]] M_Jupiter [[Jupiter mass|''M''<sub>J</sub>]] R_Jupiter [[Jupiter radius|''R''<sub>J</sub>]] Solar mass [[Solar mass|''M''<sub>&#x2609;</sub>]] solar mass [[Solar mass|''M''<sub>&#x2609;</sub>]] M_Solar [[Solar mass|''M''<sub>&#x2609;</sub>]] M_solar [[Solar mass|''M''<sub>&#x2609;</sub>]] R_Solar [[Solar radius|''R''<sub>&#x2609;</sub>]] R_solar [[Solar radius|''R''<sub>&#x2609;</sub>]] Solar radius [[Solar radius|''R''<sub>&#x2609;</sub>]] solar radius [[Solar radius|''R''<sub>&#x2609;</sub>]] Solar luminosity [[Solar luminosity|''L''<sub>&#x2609;</sub>]] solar luminosity [[Solar luminosity|''L''<sub>&#x2609;</sub>]] L_solar [[Solar luminosity|''L''<sub>&#x2609;</sub>]] L_Solar [[Solar luminosity|''L''<sub>&#x2609;</sub>]] Lo [[Solar luminosity|''L''<sub>&#x2609;</sub>]] pc2 [[Parsec|pc<sup>2</sup>]] pc3 [[Parsec|pc<sup>3</sup>]] kpc2 [[Parsec#Parsecs and kiloparsecs|kpc<sup>2</sup>]] kpc3 [[Parsec#Parsecs and kiloparsecs|kpc<sup>3</sup>]] kpc [[Parsec#Parsecs and kiloparsecs|kpc]] Mpc2 [[Parsec#Megaparsecs and gigaparsecs|Mpc<sup>2</sup>]] Mpc3 [[Parsec#Megaparsecs and gigaparsecs|Mpc<sup>3</sup>]] Mpc [[Parsec#Megaparsecs and gigaparsecs|Mpc]] Gpc2 [[Parsec#Megaparsecs and gigaparsecs|Gpc<sup>2</sup>]] Gpc3 [[Parsec#Megaparsecs and gigaparsecs|Gpc<sup>3</sup>]] Gpc [[Parsec#Megaparsecs and gigaparsecs|Gpc]] == Nuclear physics and chemistry == cm-1 [[Wavenumber|cm<sup>−1</sup>]] u [[Unified atomic mass unit|u]] osmol [[Osmole (unit)|osmol]] Osm [[Osmole (unit)|Osm]] M [[Molarity|M]] TM [[Molarity|M]] SI GM [[Molarity|M]] SI MM [[Molarity|M]] SI kM [[Molarity|M]] SI hM [[Molarity|M]] SI daM [[Molarity|M]] SI dM [[Molarity|M]] SI cM [[Molarity|M]] SI mM [[Molarity|M]] SI uM [[Molarity|M]] 1e-6 nM [[Molarity|M]] SI pM [[Molarity|M]] SI kg.mol-1 [[Molar mass|kg&sdot;mol<sup>−1</sup>]] kg/mol [[Molar mass|kg/mol]] g.mol-1 [[Molar mass|g&sdot;mol<sup>−1</sup>]] g/mol [[Molar mass|g/mol]] eV/c2 [[Electronvolt#Mass|eV/''c''<sup>2</sup>]] keV/c2 [[Electronvolt#Mass|keV/''c''<sup>2</sup>]] MeV/c2 [[Electronvolt#Mass|MeV/''c''<sup>2</sup>]] GeV/c2 [[Electronvolt#Mass|GeV/''c''<sup>2</sup>]] TeV/c2 [[Electronvolt#Mass|TeV/''c''<sup>2</sup>]] eV [[Electronvolt|eV]] meV [[Electronvolt|meV]] keV [[Electronvolt|keV]] MeV [[Electronvolt|MeV]] GeV [[Electronvolt|GeV]] TeV [[Electronvolt|TeV]] mol-1 [[Avogadro constant|mol<sup>−1</sup>]] J.mol-1 [[Joule per mole|J&sdot;mol<sup>−1</sup>]] J/mol [[Joule per mole|J/mol]] kJ.mol-1 [[Joule per mole|kJ&sdot;mol<sup>−1</sup>]] kJ/mol [[Joule per mole|kJ/mol]] MJ.mol-1 [[Joule per mole|MJ&sdot;mol<sup>−1</sup>]] MJ/mol [[Joule per mole|MJ/mol]] GJ.mol-1 [[Joule per mole|GJ&sdot;mol<sup>−1</sup>]] GJ/mol [[Joule per mole|GJ/mol]] TJ.mol-1 [[Joule per mole|TJ&sdot;mol<sup>−1</sup>]] TJ/mol [[Joule per mole|TJ/mol]] == Numbers and phrases == pp [[Page (paper)|pp]] ppb [[Parts per billion|ppb]] 1e-9 ppm [[Parts per million|ppm]] 1e-6 billiard [[Orders of magnitude (numbers)#1015|billiard]] 1e15 billion [[1,000,000,000|billion]] 1e9 billionth [[1,000,000,000|billionth]] 1e-9 billionths [[1,000,000,000|billionths]] 1e-9 decilliard [[Orders of magnitude (numbers)#1063|decilliard]] 1e63 decillion [[Orders of magnitude (numbers)#1033|decillion]] 1e33 decillionth [[Orders of magnitude (numbers)#1033|decillionth]] 1e-33 decillionths [[Orders of magnitude (numbers)#1033|decillionths]] 1e-33 milliard [[1,000,000,000|milliard]] 1e9 million [[Million|million]] 1e6 millionth [[Million|millionth]] 1e-6 millionths [[Million|millionths]] 1e-6 nonilliard [[Orders of magnitude (numbers)#1057|nonilliard]] 1e57 nonillion [[Orders of magnitude (numbers)#1030|nonillion]] 1e30 nonillionth [[Orders of magnitude (numbers)#1030|nonillionth]] 1e-30 nonillionths [[Orders of magnitude (numbers)#1030|nonillionths]] 1e-30 octilliard [[Orders of magnitude (numbers)#1051|octilliard]] 1e51 octillion [[Orders of magnitude (numbers)#1027|octillion]] 1e27 octillionth [[Orders of magnitude (numbers)#1027|octillionth]] 1e-27 octillionths [[Orders of magnitude (numbers)#1027|octillionths]] 1e-27 quadrilliard [[Orders of magnitude (numbers)#1027|quadrilliard]] 1e27 quadrillion [[Orders of magnitude (numbers)#1015|quadrillion]] 1e15 quadrillionth [[Orders of magnitude (numbers)#1015|quadrillionth]] 1e-15 quadrillionths [[Orders of magnitude (numbers)#1015|quadrillionths]] 1e-15 quintilliard [[Orders of magnitude (numbers)#1033|quintilliard]] 1e33 quintillion [[Orders of magnitude (numbers)#1018|quintillion]] 1e18 quintillionth [[Orders of magnitude (numbers)#1018|quintillionth]] 1e-18 quintillionths [[Orders of magnitude (numbers)#1018|quintillionths]] 1e-18 septilliard [[Orders of magnitude (numbers)#1045|septilliard]] 1e45 septillion [[Orders of magnitude (numbers)#1024|septillion]] 1e24 septillionth [[Orders of magnitude (numbers)#1024|septillionth]] 1e-24 septillionths [[Orders of magnitude (numbers)#1024|septillionths]] 1e-24 sextilliard [[Orders of magnitude (numbers)#1039|sextilliard]] 1e39 sextillion [[Orders of magnitude (numbers)#1021|sextillion]] 1e21 sextillionth [[Orders of magnitude (numbers)#1021|sextillionth]] 1e-21 sextillionths [[Orders of magnitude (numbers)#1021|sextillionths]] 1e-21 trilliard [[Orders of magnitude (numbers)#1021|trilliard]] 1e21 trillion [[Orders of magnitude (numbers)#1012|trillion]] 1e12 trillionth [[Orders of magnitude (numbers)#1012|trillionth]] 1e-12 trillionths [[Orders of magnitude (numbers)#1012|trillionths]] 1e-12 == Angles == % % Percent ANGLE 0.01 percent % Percent ANGLE 0.01 per cent % Percent ANGLE 0.01 ‰ ‰ Per mil ANGLE 1e-3 per mil ‰ Per mil ANGLE 1e-3 per mill ‰ Per mil ANGLE 1e-3 per mille ‰ Per mil ANGLE 1e-3 permil ‰ Per mil ANGLE 1e-3 permill ‰ Per mil ANGLE 1e-3 permille ‰ Per mil ANGLE 1e-3 ° ° Degree (angle) ANGLE pi/180 deg ° Degree (angle) ANGLE pi/180 ' ′ Minute of arc ANGLE pi/10800 ′ ′ Minute of arc ANGLE pi/10800 arcmin ′ Minute of arc ANGLE pi/10800 arcminute ′ Minute of arc ANGLE pi/10800 " ″ Second of arc ANGLE pi/648000 ″ ″ Second of arc ANGLE pi/648000 arcsec ″ Second of arc ANGLE pi/648000 arcsecond ″ Second of arc ANGLE pi/648000 mas [[Milliarcsecond|mas]] pi/648000000 ]=] -- If val has "|long scale=on" the following definitions are used -- (then, if not found here, the normal definitions are used). -- Unit code [[Link|Symbol]] Flags/Scale local builtin_units_long_scale = [=[ == Long scale numbers and phrases == billion [[Orders of magnitude (numbers)#1012|billion]] 1e12 billionth [[Orders of magnitude (numbers)#1012|billionth]] 1e-12 billionths [[Orders of magnitude (numbers)#1012|billionths]] 1e-12 decillion [[Orders of magnitude (numbers)#1060|decillion]] 1e60 decillionth [[Orders of magnitude (numbers)#1060|decillionth]] 1e-60 decillionths [[Orders of magnitude (numbers)#1060|decillionths]] 1e-60 nonillion [[Orders of magnitude (numbers)#1054|nonillion]] 1e54 nonillionth [[Orders of magnitude (numbers)#1054|nonillionth]] 1e-54 nonillionths [[Orders of magnitude (numbers)#1054|nonillionths]] 1e-54 octillion [[Orders of magnitude (numbers)#1048|octillion]] 1e48 octillionth [[Orders of magnitude (numbers)#1048|octillionth]] 1e-48 octillionths [[Orders of magnitude (numbers)#1048|octillionths]] 1e-48 quadrillion [[Orders of magnitude (numbers)#1024|quadrillion]] 1e24 quadrillionth [[Orders of magnitude (numbers)#1024|quadrillionth]] 1e-24 quadrillionths [[Orders of magnitude (numbers)#1024|quadrillionths]] 1e-24 quintillion [[Orders of magnitude (numbers)#1030|quintillion]] 1e30 quintillionth [[Orders of magnitude (numbers)#1030|quintillionth]] 1e-30 quintillionths [[Orders of magnitude (numbers)#1030|quintillionths]] 1e-30 septillion [[Orders of magnitude (numbers)#1042|septillion]] 1e42 septillionth [[Orders of magnitude (numbers)#1042|septillionth]] 1e-42 septillionths [[Orders of magnitude (numbers)#1042|septillionths]] 1e-42 sextillion [[Orders of magnitude (numbers)#1036|sextillion]] 1e36 sextillionth [[Orders of magnitude (numbers)#1036|sextillionth]] 1e-36 sextillionths [[Orders of magnitude (numbers)#1036|sextillionths]] 1e-36 trillion [[Orders of magnitude (numbers)#1018|trillion]] 1e18 trillionth [[Orders of magnitude (numbers)#1018|trillionth]] 1e-18 trillionths [[Orders of magnitude (numbers)#1018|trillionths]] 1e-18 ]=] return { builtin_units = builtin_units, builtin_units_long_scale = builtin_units_long_scale } 81ae3510367fd477db8e031a5103f8a573b86138 106 105 2022-09-04T15:24:30Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- Definitions for units known to val -- File format is two strings and a return statement with them in it: -- string in quotes [=[ ... builtin_units ... ]=]. -- string in quotes [=[ ... builtin_units_long_scale ... ]=]. -- First string, builtin_units, is short-scale, second string is long scale. -- Entry format: -- One record per line, starting in first column, having 2-4 fields. -- Field separator: two or more spaces -- Between first and second fields: two or more spaces -- Between all other fields: two or more spaces, or one or more tabs -- Entries without two spaces in them are ignored. -- There must be a blank line before the first entry and after the last. -- I.e. the first two and last two characters of the string must be newlines. -- Format of entry. Two record types: -- -- One record type is a wikilink: -- Unit-code [[ pagename | Symbol-accepts-HTML-only ]] -- Text-field separator is still two spaces. Two spaces not allowed in wikilink. -- -- The other record type is all fields: -- Unit-code symbol-accepts-HTML-only pagename#section-OK -- -- Plus there is an optional field that goes at the end after two or more spaces. -- Whether it is a number or an equation or the letters SI, -- any of these three has the same function: a wikitable sorting "scale". -- It is for sorting, and it works for either record type. -- Difference is SI can't accept HTML. But SI correctly scales any SI prefix. -- (Optional fields ALIAS and NOSPACE and ANGLE are for advanced users.) -- "Invalid unit" error: -- Using SI requires that the symbol equal unit-code, so never allows HTML. -- Any difference between SI or symbol must be an SI prefix, such as k, M, or G. -- A space at the end of an entry is an error. No space at each EOL. local builtin_units = [=[ == Test == Foo [[Hz|<samp>Foo</samp>]] Baz [[Hertz|baz<sub>0</sub>]] Baz [[Kelvins|baz<sub>0</sub>]] Bar [[Foobar|bar<abbr title="super duper">0</abbr>]] quux [[Foobar|<span title="super duper 2">bar0</span>]] == Unsorted units == c0 [[Speed of light#Numerical value, notation, and units|''c''<sub>0</sub>]] lbf [[Pound (force)|<span title="pound-force">lb<sub>F</sub></span> ]] N.s [[Newton-second|N&sdot;s]] J.K-1 [[Joule per kelvin|J&sdot;K<sup>−1</sup>]] C.mol-1 [[Faraday constant|C&sdot;mol<sup>−1</sup>]] C/mol [[Faraday constant|C/mol]] C.kg-1 [[Roentgen (unit)|C&sdot;kg<sup>−1</sup>]] C/kg [[Roentgen (unit)|C/kg]] F.m-1 [[vacuum permittivity|F&sdot;m<sup>−1</sup>]] F/m [[vacuum permittivity|F/m]] e [[Elementary charge|''e'']] kB [[Kilobyte|kB]] 8e3 KB [[Kilobyte|KB]] 8e3 MB [[Megabyte|MB]] 8e6 GB [[Gigabyte|GB]] 8e9 TB [[Terabyte|TB]] 8e12 lx [[Lux (unit)|lx]] nat [[nat (unit)|nat]] == Time and frequency == byte/s [[Data rate units|byte/s]] 8 kB/s [[Data rate units#Kilobyte per second|<span title="Kilobytes per second">kB/s</span>]] 8e3 MB/s [[Data rate units#Megabyte per second|<span title="Megabytes per second">MB/s</span>]] 8e6 GB/s [[Data rate units#Gigabyte per second|<span title="Gigabytes per second">GB/s</span>]] 8e9 TB/s [[Data rate units#Terabyte per second|<span title="Terabytes per second">TB/s</span>]] 8e12 bit/s [[Bit per second|bit/s]] 1 bps [[Bit per second|bit/s]] 1 kbit/s [[Kilobit per second|kbit/s]] 1e3 Mbit/s [[Megabit per second|Mbit/s]] 1e6 Gbit/s [[Gigabit per second|Gbit/s]] 1e9 Tbit/s [[Terabit per second|Tbit/s]] 1e12 kT/s [[Transfer (computing)|<span title="Kilotransfers per second">kT/s</span>]] 1e3 MT/s [[Transfer (computing)|<span title="Megatransfers per second">MT/s</span>]] 1e6 GT/s [[Transfer (computing)|<span title="Gigatransfers per second">GT/s</span>]] 1e9 year [[Year|year]] 31557600 years [[Year|years]] 31557600 yr [[Year#Symbols y and yr|yr]] 31557600 y [[Year|y]] 31557600 a [[Annum|a]] 31557600 Ga [[Gigaannum|Ga]] 31557600000000000 Ma [[Megaannum|Ma]] 31557600000000 ka [[Kiloannum|ka]] 31557600000 kyr [[kyr|kyr]] 31557600000 kya [[kyr|kya]] 31557600000 myr [[myr|myr]] 31557600000000 mya [[Mya (unit)|mya]] 31557600000000 byr [[Billion years|byr]] 31557600000000000 bya [[Billion years ago|bya]] 31557600000000000 Gyr [[billion years|Gyr]] 31557600000000000 BP [[Before present|BP]] uBP [[Radiocarbon dating#Calibration|<sup>14</sup>C yr BP]] BC [[Before Christ|BC]] -1 AD [[Anno Domini|AD]] 1 BCE [[Before the Common Era|BCE]] -1 CE [[Common Era|CE]] 1 JD [[Julian date|JD]] 1 MJD [[Modified Julian date|MJD]] 1 s-1 [[Second|s<sup>−1</sup>]] s-2 [[Second|s<sup>−2</sup>]] s2 [[Second|s<sup>2</sup>]] s [[Second|s]] SI as [[Attosecond|s]] SI cs [[Second|s]] SI das [[Second|s]] SI ds [[Second|s]] SI Es [[Second|s]] SI fs [[Femtosecond|s]] SI Gs [[Second|s]] SI hs [[Second|s]] SI ks [[Second|s]] SI ms [[Millisecond|s]] SI µs [[Microsecond|s]] SI us [[Microsecond|s]] SI Ms [[Second|s]] SI ns [[Nanosecond|s]] SI ps [[Picosecond|s]] SI Ps [[Second|s]] SI Ts [[Second|s]] SI Ys [[Second|s]] SI ys [[Yoctosecond|s]] SI Zs [[Second|s]] SI zs [[Zeptosecond|s]] SI Hz [[Hertz|Hz]] SI aHz [[Hertz|Hz]] SI cHz [[Hertz|Hz]] SI daHz [[Hertz|Hz]] SI dHz [[Hertz|Hz]] SI EHz [[Hertz|Hz]] SI fHz [[Hertz|Hz]] SI hHz [[Hertz|Hz]] SI GHz [[Gigahertz|Hz]] SI kHz [[Kilohertz|Hz]] SI MHz [[Megahertz|Hz]] SI mHz [[Hertz|Hz]] SI uHz [[Hertz|Hz]] SI µHz [[Hertz|Hz]] SI nHz [[Hertz|Hz]] SI pHz [[Hertz|Hz]] SI PHz [[Hertz|Hz]] SI THz [[Hertz|Hz]] SI yHz [[Hertz|Hz]] SI YHz [[Hertz|Hz]] SI zHz [[Hertz|Hz]] SI ZHz [[Hertz|Hz]] SI ips [[Inch per second|ips]] == Length, area, volume == Å3 [[Ångström|Å<sup>3</sup>]] fb-1 [[Barn (unit)|fb<sup>−1</sup>]] m-1 [[Metre|m<sup>−1</sup>]] m-2 [[Square metre|m<sup>−2</sup>]] m-3 [[Cubic metre|m<sup>−3</sup>]] km2 [[Square kilometre|km<sup>2</sup>]] km3 [[Cubic kilometre|km<sup>3</sup>]] µm2 [[Square metre|µm<sup>2</sup>]] um2 [[Square metre|µm<sup>2</sup>]] am2 [[Square metre|am<sup>2</sup>]] cm2 [[Square centimetre|cm<sup>2</sup>]] dam2 [[Square metre|dam<sup>2</sup>]] dm2 [[Square metre|dm<sup>2</sup>]] Em2 [[Square metre|Em<sup>2</sup>]] fm2 [[Square metre|fm<sup>2</sup>]] Gm2 [[Square metre|Gm<sup>2</sup>]] hm2 [[Square metre|hm<sup>2</sup>]] mm2 [[Square metre|mm<sup>2</sup>]] Mm2 [[Square metre|Mm<sup>2</sup>]] nm2 [[Square metre|nm<sup>2</sup>]] pm2 [[Square metre|pm<sup>2</sup>]] Pm2 [[Square metre|Pm<sup>2</sup>]] Tm2 [[Square metre|Tm<sup>2</sup>]] ym2 [[Square metre|ym<sup>2</sup>]] Ym2 [[Square metre|Ym<sup>2</sup>]] zm2 [[Square metre|zm<sup>2</sup>]] Zm2 [[Square metre|Zm<sup>2</sup>]] gal [[Gallon|gal]] Gal [[Gal (unit)|Gal]] uGal [[Gal (unit)|µGal]] µGal [[Gal (unit)|µGal]] mGal [[Gal (unit)|mGal]] b [[Barn (unit)|b]] SI ab [[Barn (unit)|b]] SI cb [[Barn (unit)|b]] SI dab [[Barn (unit)|b]] SI db [[Barn (unit)|b]] SI Eb [[Barn (unit)|b]] SI fb [[Barn (unit)|b]] SI Gb [[Barn (unit)|b]] SI hb [[Barn (unit)|b]] SI kb [[Barn (unit)|b]] SI mb [[Barn (unit)|b]] SI µb [[Barn (unit)|b]] SI ub [[Barn (unit)|b]] SI Mb [[Barn (unit)|b]] SI nb [[Barn (unit)|b]] SI pb [[Barn (unit)|b]] SI Pb [[Barn (unit)|b]] SI Tb [[Barn (unit)|b]] SI Yb [[Barn (unit)|b]] SI yb [[Barn (unit)|b]] SI Zb [[Barn (unit)|b]] SI zb [[Barn (unit)|b]] SI == Velocity and acceleration == m.s-2 [[Metre per second squared|m&sdot;s<sup>−2</sup>]] m/s2 [[Metre per second squared|m/s<sup>2</sup>]] m.s-1 [[Metre per second|m&sdot;s<sup>−1</sup>]] m/s [[Metre per second|m/s]] km.s-1 [[Metre per second|km&sdot;s<sup>−1</sup>]] km/s [[Metre per second|km/s]] == Mass and energy == lbm [[Pound (mass)|<span title="pound-mass">lb<sub>m</sub></span>]] uJ [[Joule|µJ]] J.s [[Joule-second|J&sdot;s]] kWh [[Kilowatt hour|kWh]] kW.h [[Kilowatt hour|kW&sdot;h]] J/C [[Volt|J/C]] J/kg [[Joule|J/kg]] Da [[Dalton (unit)|Da]] SI EDa [[Dalton (unit)|Da]] SI PDa [[Dalton (unit)|Da]] SI TDa [[Dalton (unit)|Da]] SI GDa [[Dalton (unit)|Da]] SI MDa [[Dalton (unit)|Da]] SI kDa [[Dalton (unit)|Da]] SI mDa [[Dalton (unit)|Da]] SI uDa [[Dalton (unit)|Da]] SI μDa [[Dalton (unit)|Da]] SI nDa [[Dalton (unit)|Da]] SI pDa [[Dalton (unit)|Da]] SI fDa [[Dalton (unit)|Da]] SI aDa [[Dalton (unit)|Da]] SI g [[Gram|g]] SI ag [[Attogram|g]] SI cg [[Centigram|g]] SI dag [[Gram|g]] SI dg [[Decigram|g]] SI Eg [[Exagram|g]] SI fg [[Femtogram|g]] SI Gg [[Gigagram|g]] SI hg [[Kilogram#SI multiples|g]] SI kg [[Kilogram|g]] SI mcg [[Microgram|g]] SI Mg [[Megagram|g]] SI mg [[Milligram|g]] SI ug [[Microgram|g]] SI µg [[Microgram|g]] SI ng [[Nanogram|g]] SI Pg [[Petagram|g]] SI pg [[Picogram|g]] SI Tg [[Tonne|g]] SI yg [[Yoctogram|g]] SI Yg [[Yottagram|g]] SI zg [[Zeptogram|g]] SI Zg [[Zettagram|g]] SI == Pressure and density == psi [[Pounds per square inch|psi]] g.cm-3 [[Gram per cubic centimetre|g&sdot;cm<sup>−3</sup>]] g/cm3 [[Gram per cubic centimetre|g/cm<sup>3</sup>]] kg.m-3 [[Kilogram per cubic metre|kg&sdot;m<sup>−3</sup>]] kg/m3 [[Kilogram per cubic metre|kg/m<sup>3</sup>]] kg/cm3 [[Density#Formula and common units|kg/cm<sup>3</sup>]] g/L [[Gram per litre|g/L]] g/l [[Gram per litre|g/l]] mcg/dL [[Gram per litre|µg/dL]] mcg/dl [[Gram per litre|µg/dl]] mg/mL [[Gram per litre|mg/mL]] mg/ml [[Gram per litre|mg/ml]] ug/dL [[Gram per litre|µg/dL]] ug/dl [[Gram per litre|µg/dl]] μg/dL [[Gram per litre|μg/dL]] μg/dl [[Gram per litre|μg/dl]] mg.L-1 [[Gram per litre|<abbr title="milligrams per liter">mg/L</abbr>]] mg/L [[Gram per litre|<abbr title="milligrams per liter">mg/L</abbr>]] mg.l-1 [[Gram per litre|<abbr title="milligrams per liter">mg/l</abbr>]] mg/l [[Gram per litre|<abbr title="milligrams per liter">mg/l</abbr>]] == Fracture toughness == MPa.m.5 [[Fracture toughness|MPa&sdot;m<sup>1/2</sup>]] kPa.m.5 [[Fracture toughness|kPa&sdot;m<sup>1/2</sup>]] Pa.m.5 [[Fracture toughness|Pa&sdot;m<sup>1/2</sup>]] == Temperature == degC °C ALIAS degF °F ALIAS degR °R ALIAS K [[Kelvin|K]] SI YK [[Yottakelvin|K]] SI ZK [[Zettakelvin|K]] SI EK [[Kelvin|K]] SI PK [[Petakelvin|K]] SI TK [[Terakelvin|K]] SI GK [[Gigakelvin|K]] SI MK [[Megakelvin|K]] SI kK [[Kilokelvin|K]] SI hK [[Hectokelvin|K]] SI daK [[Decakelvin|K]] SI dK [[Decikelvin|K]] SI cK [[Centikelvin|K]] SI mK [[Millikelvin|K]] SI µK [[Microkelvin|K]] SI uK [[Microkelvin|K]] SI nK [[Nanokelvin|K]] SI pK [[Picokelvin|K]] SI fK [[Femtokelvin|K]] SI aK [[Attokelvin|K]] SI zK [[Zeptokelvin|K]] SI yK [[Yoctokelvin|K]] SI == Electromagnetism == Wb [[Weber (unit)|Wb]] N.A-2 [[Permeability (electromagnetism)|N&sdot;A<sup>−2</sup>]] H.m-1 [[Permeability (electromagnetism)|H&sdot;m<sup>−1</sup>]] V.m-1 [[Electric field|V&sdot;m<sup>−1</sup>]] V/m [[Electric field|V/m]] C [[Coulomb|C]] SI YC [[Coulomb|C]] SI ZC [[Coulomb|C]] SI EC [[Coulomb|C]] SI PC [[Coulomb|C]] SI TC [[Coulomb|C]] SI GC [[Coulomb|C]] SI MC [[Coulomb|C]] SI kC [[Coulomb|C]] SI hC [[Coulomb|C]] SI daC [[Coulomb|C]] SI dC [[Coulomb|C]] SI cC [[Coulomb|C]] SI mC [[Coulomb|C]] SI µC [[Coulomb|C]] SI uC [[Coulomb|C]] SI nC [[Coulomb|C]] SI pC [[Coulomb|C]] SI fC [[Coulomb|C]] SI aC [[Coulomb|C]] SI zC [[Coulomb|C]] SI yC [[Coulomb|C]] SI F [[Farad|F]] SI YF [[Farad|F]] SI ZF [[Farad|F]] SI EF [[Farad|F]] SI PF [[Farad|F]] SI TF [[Farad|F]] SI GF [[Farad|F]] SI MF [[Farad|F]] SI kF [[Farad|F]] SI hF [[Farad|F]] SI daF [[Farad|F]] SI dF [[Farad|F]] SI cF [[Farad|F]] SI mF [[Farad|F]] SI µF [[Farad|F]] SI uF [[Farad|F]] SI nF [[Farad|F]] SI pF [[Farad|F]] SI fF [[Farad|F]] SI aF [[Farad|F]] SI zF [[Farad|F]] SI yF [[Farad|F]] SI H [[Henry (unit)|H]] SI YH [[Henry (unit)|H]] SI ZH [[Henry (unit)|H]] SI EH [[Henry (unit)|H]] SI PH [[Henry (unit)|H]] SI TH [[Henry (unit)|H]] SI GH [[Henry (unit)|H]] SI MH [[Henry (unit)|H]] SI kH [[Henry (unit)|H]] SI hH [[Henry (unit)|H]] SI daH [[Henry (unit)|H]] SI dH [[Henry (unit)|H]] SI cH [[Henry (unit)|H]] SI mH [[Henry (unit)|H]] SI µH [[Henry (unit)|H]] SI uH [[Henry (unit)|H]] SI nH [[Henry (unit)|H]] SI pH [[Henry (unit)|H]] SI fH [[Henry (unit)|H]] SI aH [[Henry (unit)|H]] SI zH [[Henry (unit)|H]] SI yH [[Henry (unit)|H]] SI A [[Ampere|A]] SI YA [[Ampere|A]] SI ZA [[Ampere|A]] SI EA [[Ampere|A]] SI PA [[Ampere|A]] SI TA [[Ampere|A]] SI GA [[Ampere|A]] SI MA [[Ampere|A]] SI kA [[Ampere|A]] SI hA [[Ampere|A]] SI daA [[Ampere|A]] SI dA [[Ampere|A]] SI cA [[Ampere|A]] SI mA [[Ampere|A]] SI µA [[Ampere|A]] SI uA [[Ampere|A]] SI nA [[Ampere|A]] SI pA [[Ampere|A]] SI fA [[Ampere|A]] SI aA [[Ampere|A]] SI zA [[Ampere|A]] SI yA [[Ampere|A]] SI V [[Volt|V]] SI YV [[Volt|V]] SI ZV [[Volt|V]] SI EV [[Volt|V]] SI PV [[Volt|V]] SI TV [[Volt|V]] SI GV [[Volt|V]] SI MV [[Volt|V]] SI kV [[Volt|V]] SI hV [[Volt|V]] SI daV [[Volt|V]] SI dV [[Volt|V]] SI cV [[Volt|V]] SI mV [[Volt|V]] SI µV [[Volt|V]] SI uV [[Volt|V]] SI nV [[Volt|V]] SI pV [[Volt|V]] SI fV [[Volt|V]] SI aV [[Volt|V]] SI zV [[Volt|V]] SI yV [[Volt|V]] SI VA [[Volt-ampere|VA]] SI YVA [[Volt-ampere|VA]] SI ZVA [[Volt-ampere|VA]] SI EVA [[Volt-ampere|VA]] SI PVA [[Volt-ampere|VA]] SI TVA [[Volt-ampere|VA]] SI GVA [[Volt-ampere|VA]] SI MVA [[Volt-ampere|VA]] SI kVA [[Volt-ampere|VA]] SI hVA [[Volt-ampere|VA]] SI daVA [[Volt-ampere|VA]] SI dVA [[Volt-ampere|VA]] SI cVA [[Volt-ampere|VA]] SI mVA [[Volt-ampere|VA]] SI µVA [[Volt-ampere|VA]] SI uVA [[Volt-ampere|VA]] SI nVA [[Volt-ampere|VA]] SI pVA [[Volt-ampere|VA]] SI fVA [[Volt-ampere|VA]] SI aVA [[Volt-ampere|VA]] SI zVA [[Volt-ampere|VA]] SI yVA [[Volt-ampere|VA]] SI Ω [[Ohm|Ω]] SI YΩ.m [[Electrical resistivity and conductivity#Definition|YΩ&sdot;m]] 1e24 ZΩ.m [[Electrical resistivity and conductivity#Definition|ZΩ&sdot;m]] 1e21 EΩ.m [[Electrical resistivity and conductivity#Definition|EΩ&sdot;m]] 1e18 PΩ.m [[Electrical resistivity and conductivity#Definition|PΩ&sdot;m]] 1e15 TΩ.m [[Electrical resistivity and conductivity#Definition|TΩ&sdot;m]] 1e12 GΩ.m [[Electrical resistivity and conductivity#Definition|GΩ&sdot;m]] 1e9 MΩ.m [[Electrical resistivity and conductivity#Definition|MΩ&sdot;m]] 1e6 kΩ.m [[Electrical resistivity and conductivity#Definition|kΩ&sdot;m]] 1e3 Ω.m [[Electrical resistivity and conductivity#Definition|Ω&sdot;m]] 1 mΩ.m [[Electrical resistivity and conductivity#Definition|mΩ&sdot;m]] 1e-3 µΩ.m [[Electrical resistivity and conductivity#Definition|µΩ&sdot;m]] 1e-6 uΩ.m [[Electrical resistivity and conductivity#Definition|µΩ&sdot;m]] 1e-6 nΩ.m [[Electrical resistivity and conductivity#Definition|nΩ&sdot;m]] 1e-9 pΩ.m [[Electrical resistivity and conductivity#Definition|pΩ&sdot;m]] 1e-12 fΩ.m [[Electrical resistivity and conductivity#Definition|fΩ&sdot;m]] 1e-15 aΩ.m [[Electrical resistivity and conductivity#Definition|aΩ&sdot;m]] 1e-18 zΩ.m [[Electrical resistivity and conductivity#Definition|zΩ&sdot;m]] 1e-21 yΩ.m [[Electrical resistivity and conductivity#Definition|yΩ&sdot;m]] 1e-24 R [[Rayleigh (unit)|R]] SI G [[Gauss (unit)|G]] SI aG [[Attogauss|G]] SI cG [[Centigauss|G]] SI daG [[Decagauss|G]] SI dG [[Decigauss|G]] SI EG [[Exagauss|G]] SI fG [[Femtogauss|G]] SI GG [[Gigagauss|G]] SI hG [[Hectogauss|G]] SI kG [[Kilogauss|G]] SI MG [[Megagauss|G]] SI mG [[Milligauss|G]] SI uG [[Microgauss|G]] SI µG [[Microgauss|G]] SI nG [[Nanogauss|G]] SI PG [[Petagauss|G]] SI pG [[Picogauss|G]] SI TG [[Teragauss|G]] SI yG [[Yoctogauss|G]] SI YG [[Yottagauss|G]] SI zG [[Zeptogauss|G]] SI ZG [[Zettagauss|G]] SI T [[Tesla (unit)|T]] SI aT [[Attotesla|T]] SI cT [[Centitesla|T]] SI daT [[Decatesla|T]] SI dT [[Decitesla|T]] SI ET [[Exatesla|T]] SI fT [[Femtotesla|T]] SI GT [[Gigatesla|T]] SI hT [[Hectotesla|T]] SI kT [[Kilotesla|T]] SI MT [[Megatesla|T]] SI mT [[Millitesla|T]] SI uT [[Microtesla|T]] SI µT [[Microtesla|T]] SI nT [[Nanotesla|T]] SI PT [[Petatesla|T]] SI pT [[Picotesla|T]] SI TT [[Teratesla|T]] SI yT [[Yoctotesla|T]] SI YT [[Yottatesla|T]] SI zT [[Zeptotesla|T]] SI ZT [[Zettatesla|T]] SI == Astrophysics == au [[Astronomical unit|au]] c [[Speed of light|''c'']] ly [[Light-year|ly]] dex [[decimal exponent|dex]] Earth mass [[Earth mass|''M''<sub>🜨</sub>]] Earth radius [[Earth radius|''R''<sub>🜨</sub>]] M_Earth [[Earth mass|''M''<sub>🜨</sub>]] R_Earth [[Earth radius|''R''<sub>🜨</sub>]] M+ [[Earth mass|''M''<sub>🜨</sub>]] R+ [[Earth radius|''R''<sub>🜨</sub>]] Jupiter mass [[Jupiter mass|''M''<sub>J</sub>]] Jupiter radius [[Jupiter radius|''R''<sub>J</sub>]] M_Jupiter [[Jupiter mass|''M''<sub>J</sub>]] R_Jupiter [[Jupiter radius|''R''<sub>J</sub>]] Solar mass [[Solar mass|''M''<sub>&#x2609;</sub>]] solar mass [[Solar mass|''M''<sub>&#x2609;</sub>]] M_Solar [[Solar mass|''M''<sub>&#x2609;</sub>]] M_solar [[Solar mass|''M''<sub>&#x2609;</sub>]] R_Solar [[Solar radius|''R''<sub>&#x2609;</sub>]] R_solar [[Solar radius|''R''<sub>&#x2609;</sub>]] Solar radius [[Solar radius|''R''<sub>&#x2609;</sub>]] solar radius [[Solar radius|''R''<sub>&#x2609;</sub>]] Solar luminosity [[Solar luminosity|''L''<sub>&#x2609;</sub>]] solar luminosity [[Solar luminosity|''L''<sub>&#x2609;</sub>]] L_solar [[Solar luminosity|''L''<sub>&#x2609;</sub>]] L_Solar [[Solar luminosity|''L''<sub>&#x2609;</sub>]] Lo [[Solar luminosity|''L''<sub>&#x2609;</sub>]] pc2 [[Parsec|pc<sup>2</sup>]] pc3 [[Parsec|pc<sup>3</sup>]] kpc2 [[Parsec#Parsecs and kiloparsecs|kpc<sup>2</sup>]] kpc3 [[Parsec#Parsecs and kiloparsecs|kpc<sup>3</sup>]] kpc [[Parsec#Parsecs and kiloparsecs|kpc]] Mpc2 [[Parsec#Megaparsecs and gigaparsecs|Mpc<sup>2</sup>]] Mpc3 [[Parsec#Megaparsecs and gigaparsecs|Mpc<sup>3</sup>]] Mpc [[Parsec#Megaparsecs and gigaparsecs|Mpc]] Gpc2 [[Parsec#Megaparsecs and gigaparsecs|Gpc<sup>2</sup>]] Gpc3 [[Parsec#Megaparsecs and gigaparsecs|Gpc<sup>3</sup>]] Gpc [[Parsec#Megaparsecs and gigaparsecs|Gpc]] == Nuclear physics and chemistry == cm-1 [[Wavenumber|cm<sup>−1</sup>]] u [[Unified atomic mass unit|u]] osmol [[Osmole (unit)|osmol]] Osm [[Osmole (unit)|Osm]] M [[Molarity|M]] TM [[Molarity|M]] SI GM [[Molarity|M]] SI MM [[Molarity|M]] SI kM [[Molarity|M]] SI hM [[Molarity|M]] SI daM [[Molarity|M]] SI dM [[Molarity|M]] SI cM [[Molarity|M]] SI mM [[Molarity|M]] SI uM [[Molarity|M]] 1e-6 nM [[Molarity|M]] SI pM [[Molarity|M]] SI kg.mol-1 [[Molar mass|kg&sdot;mol<sup>−1</sup>]] kg/mol [[Molar mass|kg/mol]] g.mol-1 [[Molar mass|g&sdot;mol<sup>−1</sup>]] g/mol [[Molar mass|g/mol]] eV/c2 [[Electronvolt#Mass|eV/''c''<sup>2</sup>]] keV/c2 [[Electronvolt#Mass|keV/''c''<sup>2</sup>]] MeV/c2 [[Electronvolt#Mass|MeV/''c''<sup>2</sup>]] GeV/c2 [[Electronvolt#Mass|GeV/''c''<sup>2</sup>]] TeV/c2 [[Electronvolt#Mass|TeV/''c''<sup>2</sup>]] eV [[Electronvolt|eV]] meV [[Electronvolt|meV]] keV [[Electronvolt|keV]] MeV [[Electronvolt|MeV]] GeV [[Electronvolt|GeV]] TeV [[Electronvolt|TeV]] mol-1 [[Avogadro constant|mol<sup>−1</sup>]] J.mol-1 [[Joule per mole|J&sdot;mol<sup>−1</sup>]] J/mol [[Joule per mole|J/mol]] kJ.mol-1 [[Joule per mole|kJ&sdot;mol<sup>−1</sup>]] kJ/mol [[Joule per mole|kJ/mol]] MJ.mol-1 [[Joule per mole|MJ&sdot;mol<sup>−1</sup>]] MJ/mol [[Joule per mole|MJ/mol]] GJ.mol-1 [[Joule per mole|GJ&sdot;mol<sup>−1</sup>]] GJ/mol [[Joule per mole|GJ/mol]] TJ.mol-1 [[Joule per mole|TJ&sdot;mol<sup>−1</sup>]] TJ/mol [[Joule per mole|TJ/mol]] == Numbers and phrases == pp [[Page (paper)|pp]] ppb [[Parts per billion|ppb]] 1e-9 ppm [[Parts per million|ppm]] 1e-6 billiard [[Orders of magnitude (numbers)#1015|billiard]] 1e15 billion [[1,000,000,000|billion]] 1e9 billionth [[1,000,000,000|billionth]] 1e-9 billionths [[1,000,000,000|billionths]] 1e-9 decilliard [[Orders of magnitude (numbers)#1063|decilliard]] 1e63 decillion [[Orders of magnitude (numbers)#1033|decillion]] 1e33 decillionth [[Orders of magnitude (numbers)#1033|decillionth]] 1e-33 decillionths [[Orders of magnitude (numbers)#1033|decillionths]] 1e-33 milliard [[1,000,000,000|milliard]] 1e9 million [[Million|million]] 1e6 millionth [[Million|millionth]] 1e-6 millionths [[Million|millionths]] 1e-6 nonilliard [[Orders of magnitude (numbers)#1057|nonilliard]] 1e57 nonillion [[Orders of magnitude (numbers)#1030|nonillion]] 1e30 nonillionth [[Orders of magnitude (numbers)#1030|nonillionth]] 1e-30 nonillionths [[Orders of magnitude (numbers)#1030|nonillionths]] 1e-30 octilliard [[Orders of magnitude (numbers)#1051|octilliard]] 1e51 octillion [[Orders of magnitude (numbers)#1027|octillion]] 1e27 octillionth [[Orders of magnitude (numbers)#1027|octillionth]] 1e-27 octillionths [[Orders of magnitude (numbers)#1027|octillionths]] 1e-27 quadrilliard [[Orders of magnitude (numbers)#1027|quadrilliard]] 1e27 quadrillion [[Orders of magnitude (numbers)#1015|quadrillion]] 1e15 quadrillionth [[Orders of magnitude (numbers)#1015|quadrillionth]] 1e-15 quadrillionths [[Orders of magnitude (numbers)#1015|quadrillionths]] 1e-15 quintilliard [[Orders of magnitude (numbers)#1033|quintilliard]] 1e33 quintillion [[Orders of magnitude (numbers)#1018|quintillion]] 1e18 quintillionth [[Orders of magnitude (numbers)#1018|quintillionth]] 1e-18 quintillionths [[Orders of magnitude (numbers)#1018|quintillionths]] 1e-18 septilliard [[Orders of magnitude (numbers)#1045|septilliard]] 1e45 septillion [[Orders of magnitude (numbers)#1024|septillion]] 1e24 septillionth [[Orders of magnitude (numbers)#1024|septillionth]] 1e-24 septillionths [[Orders of magnitude (numbers)#1024|septillionths]] 1e-24 sextilliard [[Orders of magnitude (numbers)#1039|sextilliard]] 1e39 sextillion [[Orders of magnitude (numbers)#1021|sextillion]] 1e21 sextillionth [[Orders of magnitude (numbers)#1021|sextillionth]] 1e-21 sextillionths [[Orders of magnitude (numbers)#1021|sextillionths]] 1e-21 trilliard [[Orders of magnitude (numbers)#1021|trilliard]] 1e21 trillion [[Orders of magnitude (numbers)#1012|trillion]] 1e12 trillionth [[Orders of magnitude (numbers)#1012|trillionth]] 1e-12 trillionths [[Orders of magnitude (numbers)#1012|trillionths]] 1e-12 == Angles == % % Percent ANGLE 0.01 percent % Percent ANGLE 0.01 per cent % Percent ANGLE 0.01 ‰ ‰ Per mil ANGLE 1e-3 per mil ‰ Per mil ANGLE 1e-3 per mill ‰ Per mil ANGLE 1e-3 per mille ‰ Per mil ANGLE 1e-3 permil ‰ Per mil ANGLE 1e-3 permill ‰ Per mil ANGLE 1e-3 permille ‰ Per mil ANGLE 1e-3 ° ° Degree (angle) ANGLE pi/180 deg ° Degree (angle) ANGLE pi/180 ' ′ Minute of arc ANGLE pi/10800 ′ ′ Minute of arc ANGLE pi/10800 arcmin ′ Minute of arc ANGLE pi/10800 arcminute ′ Minute of arc ANGLE pi/10800 " ″ Second of arc ANGLE pi/648000 ″ ″ Second of arc ANGLE pi/648000 arcsec ″ Second of arc ANGLE pi/648000 arcsecond ″ Second of arc ANGLE pi/648000 mas [[Milliarcsecond|mas]] pi/648000000 ]=] -- If val has "|long scale=on" the following definitions are used -- (then, if not found here, the normal definitions are used). -- Unit code [[Link|Symbol]] Flags/Scale local builtin_units_long_scale = [=[ == Long scale numbers and phrases == billion [[Orders of magnitude (numbers)#1012|billion]] 1e12 billionth [[Orders of magnitude (numbers)#1012|billionth]] 1e-12 billionths [[Orders of magnitude (numbers)#1012|billionths]] 1e-12 decillion [[Orders of magnitude (numbers)#1060|decillion]] 1e60 decillionth [[Orders of magnitude (numbers)#1060|decillionth]] 1e-60 decillionths [[Orders of magnitude (numbers)#1060|decillionths]] 1e-60 nonillion [[Orders of magnitude (numbers)#1054|nonillion]] 1e54 nonillionth [[Orders of magnitude (numbers)#1054|nonillionth]] 1e-54 nonillionths [[Orders of magnitude (numbers)#1054|nonillionths]] 1e-54 octillion [[Orders of magnitude (numbers)#1048|octillion]] 1e48 octillionth [[Orders of magnitude (numbers)#1048|octillionth]] 1e-48 octillionths [[Orders of magnitude (numbers)#1048|octillionths]] 1e-48 quadrillion [[Orders of magnitude (numbers)#1024|quadrillion]] 1e24 quadrillionth [[Orders of magnitude (numbers)#1024|quadrillionth]] 1e-24 quadrillionths [[Orders of magnitude (numbers)#1024|quadrillionths]] 1e-24 quintillion [[Orders of magnitude (numbers)#1030|quintillion]] 1e30 quintillionth [[Orders of magnitude (numbers)#1030|quintillionth]] 1e-30 quintillionths [[Orders of magnitude (numbers)#1030|quintillionths]] 1e-30 septillion [[Orders of magnitude (numbers)#1042|septillion]] 1e42 septillionth [[Orders of magnitude (numbers)#1042|septillionth]] 1e-42 septillionths [[Orders of magnitude (numbers)#1042|septillionths]] 1e-42 sextillion [[Orders of magnitude (numbers)#1036|sextillion]] 1e36 sextillionth [[Orders of magnitude (numbers)#1036|sextillionth]] 1e-36 sextillionths [[Orders of magnitude (numbers)#1036|sextillionths]] 1e-36 trillion [[Orders of magnitude (numbers)#1018|trillion]] 1e18 trillionth [[Orders of magnitude (numbers)#1018|trillionth]] 1e-18 trillionths [[Orders of magnitude (numbers)#1018|trillionths]] 1e-18 ]=] return { builtin_units = builtin_units, builtin_units_long_scale = builtin_units_long_scale } 81ae3510367fd477db8e031a5103f8a573b86138 Sirius 0 33 72 2022-09-04T11:44:31Z SpaceMan 2 Created page with "Sirius is the brightest star system in Earth's night sky. The name "Sirius" is derived from the Ancient Greek "Seirios", which means "glowing" or "scorcher". What appears to be a single star to the naked eye is actually a binary system of a white star with a faint [[White dwarf]]. This system is formally known as Alpha Canis Majoris or alpha CMa. **Brightness** Sirius is the brightest star system in the night sky with almost twice the brightness of the second brightest..." wikitext text/x-wiki Sirius is the brightest star system in Earth's night sky. The name "Sirius" is derived from the Ancient Greek "Seirios", which means "glowing" or "scorcher". What appears to be a single star to the naked eye is actually a binary system of a white star with a faint [[White dwarf]]. This system is formally known as Alpha Canis Majoris or alpha CMa. **Brightness** Sirius is the brightest star system in the night sky with almost twice the brightness of the second brightest star, [[Canopus]]. However, it is not as bright as the moon, Venus or Jupiter. In fact, even [[Mars]] and [[Mercury]] appear brighter than Sirius at times. **Types of Sirius** The two stars of the Sirius system are termed as Sirius A and Sirius B. Sirius A is a white main-sequence star with an estimated surface temperature of 9,940 K. It has an estimated mass which is twice that of the Sun. Sirius B is a star that has already evolved off the main sequence and transformed into a white dwarf. It has a mass almost equal to that of the Sun. It is one of the most massive white dwarfs known to us. **Colour** Greek astronomer Ptolemy had described the star of Sirius to be red in colour around 150 CE. However, poet Marcus Manilius described it as blue in his poems around 1 CE and ancient China has been describing it as white since 4 CE. Astronomers believe that this [[Star]] keeps changing its colour. However, the reason is still being debated upon. bb380f560c64f197557d78e8b843b66ad0afe04f 73 72 2022-09-04T11:46:34Z SpaceMan 2 Protected "[[Sirius]]" ([Edit=Allow only logged in users] (indefinite)) wikitext text/x-wiki Sirius is the brightest star system in Earth's night sky. The name "Sirius" is derived from the Ancient Greek "Seirios", which means "glowing" or "scorcher". What appears to be a single star to the naked eye is actually a binary system of a white star with a faint [[White dwarf]]. This system is formally known as Alpha Canis Majoris or alpha CMa. **Brightness** Sirius is the brightest star system in the night sky with almost twice the brightness of the second brightest star, [[Canopus]]. However, it is not as bright as the moon, Venus or Jupiter. In fact, even [[Mars]] and [[Mercury]] appear brighter than Sirius at times. **Types of Sirius** The two stars of the Sirius system are termed as Sirius A and Sirius B. Sirius A is a white main-sequence star with an estimated surface temperature of 9,940 K. It has an estimated mass which is twice that of the Sun. Sirius B is a star that has already evolved off the main sequence and transformed into a white dwarf. It has a mass almost equal to that of the Sun. It is one of the most massive white dwarfs known to us. **Colour** Greek astronomer Ptolemy had described the star of Sirius to be red in colour around 150 CE. However, poet Marcus Manilius described it as blue in his poems around 1 CE and ancient China has been describing it as white since 4 CE. Astronomers believe that this [[Star]] keeps changing its colour. However, the reason is still being debated upon. bb380f560c64f197557d78e8b843b66ad0afe04f 75 73 2022-09-04T11:48:43Z SpaceMan 2 Sirius wikitext text/x-wiki [[File:Siriusstar.jpg|thumb|Sirius star]] Sirius is the brightest star system in Earth's night sky. The name "Sirius" is derived from the Ancient Greek "Seirios", which means "glowing" or "scorcher". What appears to be a single star to the naked eye is actually a binary system of a white star with a faint [[White dwarf]]. This system is formally known as Alpha Canis Majoris or alpha CMa. **Brightness** Sirius is the brightest star system in the night sky with almost twice the brightness of the second brightest star, [[Canopus]]. However, it is not as bright as the moon, Venus or Jupiter. In fact, even [[Mars]] and [[Mercury]] appear brighter than Sirius at times. **Types of Sirius** The two stars of the Sirius system are termed as Sirius A and Sirius B. Sirius A is a white main-sequence star with an estimated surface temperature of 9,940 K. It has an estimated mass which is twice that of the Sun. Sirius B is a star that has already evolved off the main sequence and transformed into a white dwarf. It has a mass almost equal to that of the Sun. It is one of the most massive white dwarfs known to us. **Colour** Greek astronomer Ptolemy had described the star of Sirius to be red in colour around 150 CE. However, poet Marcus Manilius described it as blue in his poems around 1 CE and ancient China has been describing it as white since 4 CE. Astronomers believe that this [[Star]] keeps changing its colour. However, the reason is still being debated upon. a89cb8b357886c650cd272c113268f4028ec6e91 File:Siriusstar.jpg 6 34 74 2022-09-04T11:48:12Z SpaceMan 2 Uploaded own work with UploadWizard wikitext text/x-wiki =={{int:filedesc}}== {{Information |description={{en|1=Sirius star}} |date=2022-09-04 |source={{own}} |author=[[User:SpaceMan|SpaceMan]] |permission= |other versions= }} =={{int:license-header}}== {{self|cc-by-sa-4.0}} [[Category:Star]] f0e4db20c0a645529105d4417b0ebec5c2f1b47f Astronomy Database portal 0 30 76 71 2022-09-04T11:50:00Z SpaceMan 2 /* Star */ wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from [https://cds.u-strasbg.fr/ CDS] . ==Star== [https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major] [https://astrobase.miraheze.org/wiki/Sirius Sirius] 41ff058823eed3a28416991dc9b269985d5335b4 77 76 2022-09-04T11:50:15Z SpaceMan 2 /* Star */ wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from [https://cds.u-strasbg.fr/ CDS] . ==Star== [https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major]<br> [https://astrobase.miraheze.org/wiki/Sirius Sirius] 422fd453b6f248957848919d0441bd6bb4fb86ac 83 77 2022-09-04T14:18:48Z SpaceMan 2 /* Star */ wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from [https://cds.u-strasbg.fr/ CDS] . ==Star== [https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major]<br> [https://astrobase.miraheze.org/wiki/Sirius Sirius]<br> [https://astrobase.miraheze.org/wiki/Canopus Canopus] 38eeaf4fa86e377ccaa4b0dfd3e621eac19c17b9 84 83 2022-09-04T14:19:27Z SpaceMan 2 /* Astronomy Database Portal */ wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from verious sources. ==Star== [https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major]<br> [https://astrobase.miraheze.org/wiki/Sirius Sirius]<br> [https://astrobase.miraheze.org/wiki/Canopus Canopus] 4c9f1e007ee9ad212661e57418f5bcf1f8d08d1c 85 84 2022-09-04T14:19:48Z SpaceMan 2 Protected "[[Astronomy Database portal]]" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from verious sources. ==Star== [https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major]<br> [https://astrobase.miraheze.org/wiki/Sirius Sirius]<br> [https://astrobase.miraheze.org/wiki/Canopus Canopus] 4c9f1e007ee9ad212661e57418f5bcf1f8d08d1c 87 85 2022-09-04T15:15:02Z SpaceMan 2 /* Star */ wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from verious sources. ==Star== [https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major]<br> [https://astrobase.miraheze.org/wiki/Sirius Sirius]<br> [https://astrobase.miraheze.org/wiki/Canopus Canopus] {| class="wikitable" |+STAR |- |[https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major] |- |[https://astrobase.miraheze.org/wiki/Sirius Sirius] |- |[https://astrobase.miraheze.org/wiki/Canopus Canopus] |} b89508a4c96d3a61012907cb56c1bda86a0f98e4 88 87 2022-09-04T15:15:29Z SpaceMan 2 /* Star */ wikitext text/x-wiki ==Astronomy Database Portal== This is Astronomy Database Portal (ADP). Note: following content is taken from verious sources. ==Star== {| class="wikitable" |+STAR |- |[https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major] |- |[https://astrobase.miraheze.org/wiki/Sirius Sirius] |- |[https://astrobase.miraheze.org/wiki/Canopus Canopus] |} 83bd14d43ff8a54873d17d37f7d870b73576e56e Main Page 0 1 78 66 2022-09-04T11:50:52Z SpaceMan 2 /* Welcome to {{SITENAME}}! */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == AstroBase is an online encyclopaedia for astronomy and a wiki. Currently a development. ===Quick List=== [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] ===Astronomy Database Portal=== [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 837402f9e3935893c3edda0f84dbd74e9ea20317 86 78 2022-09-04T15:06:43Z SpaceMan 2 /* Welcome to {{SITENAME}}! */ wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ == Welcome to {{SITENAME}}! == AstroBase is an online encyclopaedia for astronomy and a wiki. Currently in development. ===Quick List=== [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] ===Astronomy Database Portal=== [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 98c1a3cbd13a23527d385108656c16a36289f82c Category:Pages with reference errors 14 36 82 2022-09-04T14:15:19Z SpaceMan 2 Created page with "Star" wikitext text/x-wiki Star 85a7de6e270547e88998d71994b1464d01295177 Canopus 0 37 90 89 2022-09-04T15:24:25Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{short description|Bright giant star in the constellation of Carina}} {{Other uses}} {{Starbox begin | name=Canopus }} {{Starbox image | image=[[File:Canopus.jpg|255px]] | caption=An image of Canopus by [[Expedition 6]] }} {{Starbox observe | epoch=J2000 | constell=[[Carina (constellation)|Carina]] | pronounce={{IPAc-en|k|ə|ˈ|n|oʊ|p|ə|s}}<ref>{{OED|Canopus}}</ref> | ra={{RA|06|23|57.10988}}<ref name="van Leeuwen2007">{{cite journal | title=Validation of the new Hipparcos reduction | last1=van Leeuwen | first1=F. | journal=Astronomy and Astrophysics | volume=474 | issue=2 | pages=653–664 | date=2007 | arxiv=0708.1752 | bibcode=2007A&A...474..653V | doi=10.1051/0004-6361:20078357 | s2cid=18759600 }} [http://webviz.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b48255b3&-out.add=.&-source=I/311/hip2&recno=30362 Vizier catalog entry ]</ref> | dec={{DEC|-52|41|44.3810}}<ref name="van Leeuwen2007"/> | appmag_v=−0.74<ref name="Ducati 2002">{{cite journal | title=Catalogue of Stellar Photometry in Johnson's 11-color system | last1=Ducati | first1=J. R. | journal=CDS/ADC Collection of Electronic Catalogues | volume=2237 | pages=0 | date=2002 | bibcode=2002yCat.2237....0D }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b360304a&-out.add=.&-source=II/237/colors&recno=1155 Vizier catalog entry ]</ref> }} {{Starbox character | type= | class=A9&nbsp;II<ref name=perkins>{{cite journal|bibcode=1989ApJS...69..301G|title=The early F-type stars – Refined classification, confrontation with Stromgren photometry, and the effects of rotation|journal=Astrophysical Journal Supplement Series|volume=69|pages=301|last1=Gray|first1=R. O.|last2=Garrison|first2=R. F.|year=1989|doi=10.1086/191315}}</ref><ref>{{cite journal|bibcode=1993ASPC...45...59L|title=A Spectroscopic Study of High Galactic Latitude F Supergiant Stars|journal=Luminous High-Latitude Stars. The International Workshop on Luminous High-Latitude Stars|volume=45|pages=59|last1=Lopez-Cruz|first1=O.|last2=Garrison|first2=R. F.|year=1993}}</ref> | b-v=+0.15<ref name="Ducati 2002"/> | u-b=+0.10<ref name="Ducati 2002"/> | variable= }} {{Starbox astrometry | radial_v={{val|20.3|0.5}}<ref name="Gontcharov 2007">{{cite journal | title=Pullkovo Compilation of Radial Velocities for 39495 Hipparcos stars in a common system | last1=Gontcharov | first1=G. A. | journal=Astronomy Letters | volume=32 | issue=1 | pages=759–771 | date=2007 | bibcode=2006AstL...32..759G | doi=10.1134/S1063773706110065|arxiv = 1606.08053 | s2cid=119231169 }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b5f60fbd&-out.add=.&-source=III/252/table8&recno=9232 Vizier catalog entry ]</ref> | prop_mo_ra=19.93<ref name="van Leeuwen2007"/> | prop_mo_dec=23.24<ref name="van Leeuwen2007"/> | parallax=10.55 | p_error=0.56 | parallax_footnote=<ref name="van Leeuwen2007"/> | absmag_v=–5.71<ref name=smiljanic2006/> |arxiv = 1606.08053 }} {{Starbox detail | metal_fe=–0.07<ref name=smiljanic2006/> | mass={{Val|8.0|0.3}}<ref name=vlti>{{cite journal|bibcode=2013MNRAS.434..437C|arxiv=1306.3288|title=Fundamental parameters of 16 late-type stars derived from their angular diameter measured with VLTI/AMBER|journal=Monthly Notices of the Royal Astronomical Society|volume=434|issue=1|pages=437–450|last1=Cruzalèbes|first1=P.|last2=Jorissen|first2=A.|last3=Rabbia|first3=Y.|last4=Sacuto|first4=S.|last5=Chiavassa|first5=A.|last6=Pasquato|first6=E.|last7=Plez|first7=B.|last8=Eriksson|first8=K.|last9=Spang|first9=A.|last10=Chesneau|first10=O.|year=2013|doi=10.1093/mnras/stt1037|s2cid=49573767}}</ref>&nbsp;(2013)<br/>{{val|10.1|0.1}}<ref name=Tetzlaff2011/>&nbsp;(2011) | radius={{Val|71|4}}<ref name=vlti/>&nbsp;(2013)<br>{{val|73.3|5.2}}<ref name=DomicianoDeSouza>{{cite journal|doi=10.1051/0004-6361/202140478|title=Refined fundamental parameters of Canopus from combined near-IR interferometry and spectral energy distribution|year=2021|last1=Domiciano De Souza|first1=A.|last2=Zorec|first2=J.|last3=Millour|first3=F.|last4=Le Bouquin|first4=J.-B.|last5=Spang|first5=A.|last6=Vakili|first6=F.|journal=Astronomy & Astrophysics|volume=654|pages=A19|arxiv=2109.07153|bibcode=2021A&A...654A..19D|s2cid=237513623}}</ref>&nbsp;(2021) | gravity={{Val|1.70|0.05}}<ref name=DomicianoDeSouza/> | rotational_velocity=9<ref name=ayres2018/> | rotation={{val|298|u=days|p=≥}}<ref name=Testa2004/> | luminosity=10,700<ref name=vlti/> | temperature=7,400<ref name=ayres2018>{{cite journal |bibcode=2018ApJ...854...95A |title=Cracking the Conundrum of F-supergiant Coronae |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |year=2018 |volume=854 |issue=2 |page=95 |doi=10.3847/1538-4357/aaa6d7 |arxiv=1802.02552 |s2cid=119101035 }}</ref> | age_myr = {{val|25.1|2.5}}<ref name=Tetzlaff2011>{{cite journal | title=A catalogue of young runaway Hipparcos stars within 3 kpc from the Sun | last1=Tetzlaff | first1=N. | last2=Neuhäuser | first2=R. | last3=Hohle | first3=M. M. | journal=Monthly Notices of the Royal Astronomical Society | volume=410 | issue=1 | pages=190–200 | date=January 2011 | doi=10.1111/j.1365-2966.2010.17434.x | arxiv=1007.4883 | bibcode=2011MNRAS.410..190T | s2cid=118629873 }}</ref> }} {{Starbox catalog | names={{odlist | name=Suhayl | name2=Suhel | name3=Suhail | B=α Carinae | CPD=−52°1941 | FK5=245 | HD=45348 | HIP=30438 | HR=2326 | SAO=234480| GC=8302 }}<ref name=SIMBAD>{{cite simbad | title=alf Car | access-date=2019-03-09 }}</ref> }} {{Starbox reference | Simbad=canopus }} {{Starbox end}} '''Canopus''' is the brightest star in the southern [[constellation]] of [[Carina (constellation)|Carina]] and the [[list of brightest stars|second-brightest star]] in the [[night sky]]. It is also [[Bayer designation|designated]] '''α&nbsp;Carinae''', which is [[Latinisation of names|Latinised]] to '''Alpha&nbsp;Carinae'''. With a [[visual apparent magnitude]] of −0.74, it is outshone only by [[Sirius]]. Located around {{val|310|ul=light-years}} from the [[Sun]], Canopus is a [[bright giant]] of [[spectral type A9]], so it is essentially white when seen with the naked eye. It has a luminosity over 10,000 times the [[luminosity of the Sun]], is eight times as [[mass of the Sun|massive]], and has expanded to 71 times the [[Sun's radius]]. Its enlarged [[photosphere]] has an [[effective temperature]] of around {{val|7,400|fmt=commas|u=K}}. Canopus is undergoing [[stellar core|core]] [[helium fusion|helium burning]] and is currently in the so-called [[blue loop]] phase of its [[stellar evolution|evolution]], having already passed through the [[red-giant branch]] after exhausting the hydrogen in its core. Canopus is a [[X-ray astronomy|source of X-rays]], which are likely being emitted from its [[stellar corona|corona]]. The prominent appearance of Canopus means it has been the subject of mythological lore among many ancient peoples. Its proper name is generally considered to originate from the [[Greek mythology|mythological]] [[Canopus (mythology)|Canopus]], who was a navigator for [[Menelaus]], king of [[Sparta]]. The [[acronychal rising]] marked the date of the Ptolemaia festival in Egypt. In ancient India, it was named [[Agastya]] after the revered [[Vedas|Vedic]] sage. For Chinese astronomers, it was known as the [[Old Man of the South Pole]]. ==Nomenclature== The name ''Canopus'' is a Latinisation of the [[Ancient Greek]] name Κάνωβος/Kanôbos, recorded in Claudius Ptolemy's ''[[Almagest]]'' (c.150 AD). Eratosthenes used the same spelling.<ref name="ridpathCr"/> Hipparchos wrote it as Κάνωπος. [[John Flamsteed]] wrote Canobus,<ref>{{cite book|last=Flamsteed|first=John|title=Atlas coelestis|location=London, United Kingdom|date=1729|pages=Constellation Map of Southern Hemisphere|url=http://lhldigital.lindahall.org/u?/astro_atlas,1191}}</ref> as did [[Edmond Halley]] in his 1679 ''Catalogus Stellarum Australium''.<ref name="Halley 1679">{{cite book|last=Halley|first=Edmond|title=Catalogus stellarum australium; sive, Supplementum catalogi Tychenici, exhibens longitudines et latitudines stellarum fixarum, quae, prope polum Antarcticum sitae, in horizonte Uraniburgico Tychoni inconspicuae fuere, accurato calculo ex distantiis supputatas, & ad annum 1677 completum correctas...Accedit appendicula de rebus quibusdam astronomicis|publisher=T. James|location=London|date=1679|pages=30|url=http://babel.hathitrust.org/cgi/pt?id=mdp.39015007000170;view=1up;seq=41;size=150}}</ref> The name has two possible derivations, both listed in [[Richard Hinckley Allen]]'s seminal ''[[Star Names: Their Lore and Meaning]]''. * [[Argo Navis]] was the ship used by [[Jason]] and the Argonauts in the legend of the [[Trojan War]]. The brightest star in the constellation was given the name of a ship's pilot from another Greek legend: [[Canopus (mythology)|Canopus]], pilot of [[Menelaus]]' ship on his quest to retrieve [[Helen of Troy]] after she was taken by [[Paris (mythology)|Paris]].<ref name="hinkley63">{{cite book|first=Richard Hinckley|last=Allen|author-link=Richard Hinckley Allen|date=1963|orig-year=1899|title=Star Names: Their Lore and Meaning|pages=[https://archive.org/details/starnamestheirlo00alle/page/67 67–72]|edition=Revised|publisher=Dover Publications|location=New York|isbn=0-486-21079-0|url-access=registration|url=https://archive.org/details/starnamestheirlo00alle/page/67}}</ref> * A ruined ancient Egyptian port named [[Canopus, Egypt|Canopus]] lies near the mouth of the [[Nile]], site of the [[Battle of the Nile]]. It is speculated that its name is derived from the Egyptian [[Coptic language|Coptic]] ''Kahi Nub'' ("Golden Earth"), which refers to how Canopus would have appeared near the horizon in [[ancient Egypt]], reddened by atmospheric extinction from that position.<ref name="hinkley63"/><ref name=lynn1905>{{cite journal |bibcode=1905Obs....28..289L |title=The brightest fixed star and its name |last1=Lynn |first1=W. T. |journal=The Observatory |year=1905 |volume=28 |page=289 }}</ref> In 2016, the [[International Astronomical Union]] organized a [[IAU Working Group on Star Names|Working Group on Star Names]] (WGSN) to catalog and standardize proper names for stars.<ref name="WGSN">{{cite web | url=https://www.iau.org/science/scientific_bodies/working_groups/280/ | title=IAU Working Group on Star Names (WGSN) | website=iau.org | publisher=[[International Astronomical Union]] | access-date=22 May 2016}}</ref> The WGSN's first bulletin of July 2016 included a table of the first two batches of names approved by the WGSN, which included ''Canopus'' for this star.<ref name="WGSN1">{{cite web | url=https://www.iau.org/static/science/scientific_bodies/working_groups/280/WGSN_bulletin1.pdf | title=Bulletin of the IAU Working Group on Star Names, No. 1 | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06 }}</ref> Canopus is now included in the ''IAU Catalog of Star Names''.<ref name="IAU-CSN">{{cite web | url=https://www.iau.org/public/themes/naming_stars/ | title=IAU Catalog of Star Names | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06}}</ref> Canopus traditionally marked the rudder of the ship [[Argo Navis]].<ref>{{cite journal | title = On Frederick de Houtman's Catalogue of Southern Stars, and the Origin of the Southern Constellations | last1= Knobel|first1=E. B. |journal = [[Monthly Notices of the Royal Astronomical Society]] | volume= 77| issue= 5 | pages=414–432 [422] | bibcode = 1917MNRAS..77..414K |date=1917 | doi=10.1093/mnras/77.5.414| doi-access=free }}</ref> German celestial cartographer [[Johann Bayer]] gave it—as the brightest star in the constellation—the [[Bayer designation|designation]] of ''α&nbsp;Argus'' ([[Latinisation of names|Latinised]] to ''Alpha Argus'') in 1603. In 1763, French astronomer [[Nicolas Louis de Lacaille]] divided the huge constellation into three smaller ones,<ref name=Glass2012>{{cite book | title=Nicolas-Louis De La Caille, Astronomer and Geodesist | first=Ian Stewart | last=Glass | date=November 17, 2012 | page=73 | isbn=9780191649608 | publisher=OUP Oxford | url=https://www.google.com/books/edition/Nicolas_Louis_De_La_Caille_Astronomer_an/eZjlHAIBeRAC?hl=en&gbpv=1&pg=PT73 }}</ref> and hence Canopus became ''α&nbsp;Carinae'' ([[Latinisation of names|Latinised]] to ''Alpha Carinae''). It is listed in the [[Bright Star Catalogue]] as HR 2326, the [[Henry Draper Catalogue]] as HD 45348, and the [[Hipparcos catalogue]] as HIP 30438.<ref name=SIMBAD/> Flamsteed did not number this southern star, but [[Benjamin Apthorp Gould]] gave it the number 7 (7 G. Carinae) in his ''Uranometria Argentina''.<ref name=Gould1878>{{cite journal | title=Uranometria Argentina: Brightness and position of every fixed star, down to the seventh magnitude, within one hundred degrees of the South Pole; with atlas | last=Gould | first=Benjamin Apthorp | journal=Resultados del Observatorio Nacional Argentino | volume=1 | page=140 | date=1878 | bibcode=1879RNAO....1....1G }}</ref> An occasional name seen in English is ''Soheil'', or the feminine Soheila; in Turkish is ''Süheyl'', or the feminine Süheyla, from the Arabic name for several bright stars, سهيل ''suhayl'',<ref name="hinkley63"/> and Canopus was known as Suhel {{IPAc-en|'|s|uː|h|E|l}} in medieval times.<ref name=kunitzsch/> Alternative spellings include Suhail, Souhail, Suhilon, Suheyl, Sohayl, Suhayil, Shoel, Sohil, Soheil, Sahil, Suhayeel, Sohayil, Sihel, and Sihil.<ref name="hinkley63"/> An alternative name was ''Wazn'' "weight" or ''Haḍar'' "ground", possibly related to its low position near the horizon.<ref name="hinkley63"/> Hence comes its name in the ''[[Alfonsine tables]]'', Suhel ponderosus, a Latinization of ''Al Suhayl al Wazn''.<ref name="hinkley63"/> Its Greek name was revived during the [[Renaissance]].<ref name=kunitzsch>{{cite book |last1=Kunitzsch|first1=Paul |last2=Smart|first2=Tim |date = 2006|title = A Dictionary of Modern star Names: A Short Guide to 254 Star Names and Their Derivations |edition = 2nd rev. |publisher = Sky Publishing Corporation |location = Cambridge, Massachusetts |isbn = 978-1-931559-44-7 |page = 23}}</ref> ==Observation== [[File:Carina constellation map.svg|thumb|left|The constellation [[Carina (constellation)|Carina]] with Canopus towards the right (west)]] The Spanish Muslim astronomer [[Ibn Rushd]] went to [[Marrakesh]] (in Morocco) to observe the star in 1153, as it was invisible in his native [[Córdoba, Spain|Córdoba]], [[Al-Andalus]]. He used the different visibility in different latitudes to argue that the [[Spherical Earth|earth is round]], following [[Spherical Earth#Aristotle|Aristotle's argument]] which held that such an observation was only possible if the earth was a relatively small sphere.<ref name=ibn_rushd>{{cite encyclopedia|first1=Juan|last1=Vernet|author-link1=Juan Vernet|first2=Julio|last2=Samsó|author-link2=Julio Samsó |title=The development of Arabic science in Andalusia |page=264|editor=[[Roshdi Rashed]]|encyclopedia=Encyclopedia of the History of Arabic Science | date=1996|publisher=Routledge|isbn=978-0-415-12410-2|oclc=912501823}}</ref> English explorer [[Robert Hues]] brought Canopus to the attention of European observers in his 1592 work ''Tractatus de Globis'', along with [[Achernar]] and [[Alpha Centauri]], noting:<blockquote>"Now, therefore, there are but three [[First-magnitude star|Stars of the first magnitude]] that I could perceive in all those parts which are never seene here in England. The first of these is that bright Star in the sterne of [[Argo Navis|Argo]] which they call Canobus. The second is in the end of [[Eridanus (constellation)|Eridanus]]. The third is in the right foote of the [[Centaurus|Centaure]]."<ref>Knobel, p. 416.</ref></blockquote> [[File:Vela and Surrounding Constellations (ground-based image).jpg|right|thumb|Wide angle view showing Canopus and other prominent stars with the Milky Way|alt=A field of stars against the Milky Way background with the prominent stars and constellations labelled]] In the [[Southern Hemisphere]], Canopus and [[Sirius]] are both visible high in the sky simultaneously, and reach a [[meridian (astronomy)|meridian]] just {{val|21|u=minutes}} apart. Brighter than [[first-magnitude star|first magnitude]], Canopus can be seen by naked eye in the early twilight. Mostly visible in mid to late summer in the Southern Hemisphere, Canopus [[Culmination|culminates]] at midnight on December 27,<ref name="motz" /> and at 9 PM on February 11.<ref name="Schaaf257">Schaaf, p. 257.</ref> When seen from latitudes south of {{DEC|37|18}}&nbsp;S, Canopus is a [[circumpolar star]]. Since Canopus is so far south in the sky, it never rises in mid- to far-northern latitudes; in theory the northern limit of visibility is latitude {{DEC|37|18}} north. This is just south of [[Athens]], [[Richmond, Virginia]] (USA), and [[San Francisco]], and very close to [[Seville]] and [[Agrigento]]. It is almost exactly the latitude of [[Lick Observatory]] on [[Mount Hamilton (California)|Mt. Hamilton, California]], from which it is readily visible because of the effects of elevation and [[atmospheric refraction]], which add another degree to its apparent altitude. Under ideal conditions, it can be spotted as far north as latitude {{DEC|37|31}} from the Pacific coast.<ref>D. Gieringer, "Exploring the Tropic of Canopus", ''Astronomy'', December 1985, p.24.</ref> Another northernmost record of visibility came from [[Mount Nemrut]] in Turkey, latitude {{DEC|37|59}}.<ref>{{cite web |last1=Tezel |first1=Tunç |author-link=Tunç Tezel |url=http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |title=Zodiacal Light and Nemrut Heritage |work=The World At Night (TWAN) |access-date=17 March 2014 |date=8 Oct 2013 |archive-url=https://web.archive.org/web/20140317134955/http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |archive-date=17 March 2014 |url-status=dead }}</ref> It is more easily visible in places such as the Gulf Coast and Florida, and the island of [[Crete]] (Greece) where the best season for viewing it around 9 p.m. is during late January and early February.<ref name="motz">{{cite book|last1=Motz|first1=Lloyd|last2=Nathanson|first2=Carol|title=The Constellations: An Enthusiast's Guide to the Night Sky|publisher=Aurum Press|location=London, United Kingdom|date=1991|pages=376–77|isbn=1-85410-088-2}}</ref> Canopus has a B–V [[color index]] of +0.15—where 0 is a blue-white—indicating it is essentially white, although it has been described as yellow-white. Canopus' spectral type has been given as F0 and the incrementally warmer A9. It is less yellow than [[Altair]] or [[Procyon]], with indices measured as 0.22 and 0.42, respectively.<ref name=Hoffleit1991>{{cite book | title=Bright Star Catalogue | edition=5th Revised | last1=Hoffleit | first1=D. | last2=Warren Jr. | first2=W. H. | date=1991 | publisher=[[Centre de Données astronomiques de Strasbourg|CDS]] }}</ref> Some observers may have perceived Canopus as yellow-tinged because it is low in the sky and hence subject to atmospheric effects.<ref name="Schaaf112">Schaaf, pp. 112–13.</ref> [[Patrick Moore]] said that it never appeared anything but white to him.<ref name="moore2000">{{cite book | first1=Patrick | last1=Moore | title=Exploring the night sky with binoculars | edition=4th | publisher=Cambridge University Press | year=2000 | isbn=9780521793902 | page=[https://archive.org/details/exploringnightsk00moor/page/69 69] | url=https://archive.org/details/exploringnightsk00moor| url-access=registration }}</ref> The [[bolometric correction]] for Canopus is 0.00,<ref name=smiljanic2006/> indicating that the visual [[absolute magnitude]] and bolometric absolute magnitude are equal. Canopus was previously proposed to be a member of the [[Scorpius–Centaurus association]], however it is not located near the subgroups of that association, and has not been included as a Sco-Cen member in kinematic studies that used [[Hipparcos]] astrometric data.<ref name="deZeeuw">{{cite journal|last1=de Zeeuw|first1=P.T. |last2=Hoogerwerf|first2=R. |last3=de Bruijne|first3=J.H.J |last4=Brown|first4=A.G.A |last5=Blaauw|first5=A. |date=1999|title=A HIPPARCOS Census of the Nearby OB Associations |journal=The Astronomical Journal |volume=117 |issue=1 |pages=354–399|bibcode=1999AJ....117..354D |doi=10.1086/300682|arxiv = astro-ph/9809227 |s2cid=16098861 }}</ref> Canopus is not thought to be a member of any nearby young stellar groups.<ref name=mamajek>{{cite journal | url=https://figshare.com/articles/Canopus_B_A_Candidate_Common_Proper_Motion_Companion_to_the_Second_Brightest_Star/1132696 | title=Canopus B: A Candidate Common Proper Motion Companion to the Second Brightest Star | last=Mamajek | first=Eric | year=2014 | publisher=Figshare | doi=10.6084/m9.figshare.1132696.v3 | access-date=2020-09-10 }}</ref> In 2014, astronomer Eric Mamajek reported that an extremely magnetically active M dwarf (having strong coronal X-ray emission), 1.16 degrees south of Canopus, appears to share a [[common proper motion]] with Canopus. The projected separation of the M dwarf 2MASS J06234738-5351131 ("Canopus B") is approximately 1.9 parsecs. However, despite this large separation, it is still within the estimated tidal radius (2.9 parsecs) for the massive star Canopus.<ref name="mamajek"/> No star closer than Canopus is more luminous than it, and it has been the brightest star in Earth's night sky during three epochs over the past four million years. Other stars appear brighter only during relatively temporary periods, during which they are passing the Solar System much closer than Canopus. About 90,000 years ago, [[Sirius]] moved close enough that it became brighter than Canopus, and that will remain so for another 210,000 years. But in 480,000 years, as Sirius moves further away and appears fainter, Canopus will once again be the brightest, and will remain so for a period of about 510,000 years.<ref name="tomkin98">{{cite journal|last=Tomkin|first=Jocelyn|date=April 1998|title=Once and Future Celestial Kings|journal=Sky and Telescope|volume=95|issue=4|pages=59–63|bibcode=1998S&T....95d..59T}}</ref><!-- this all comes from same paper --> ===Role in navigation=== The southeastern wall of the [[Kaaba]] in [[Mecca]] is aligned with the rising point of Canopus, and is also named ''Janūb''.<ref>{{cite book|author=George Nicholas Atiyeh|title=The Book in the Islamic World: The Written Word and Communication in the Middle East|url=https://books.google.com/books?id=t4LEfpCW_kQC|date=1 January 1995|publisher=SUNY Press|isbn=978-0-7914-2473-5}}</ref> The [[Negev Bedouin|Bedouin]] people of the [[Negev]] and [[Sinai Peninsula|Sinai]] knew Canopus as ''Suhayl'', and used it and [[Polaris]] as the two principal stars for navigation at night. Because it disappears below the horizon in those regions, it became associated with a changeable nature, as opposed to always-visible Polaris, which was circumpolar and hence 'steadfast'.<ref>{{cite journal |last=Bailey |first=Clinton |date=1974 |title=Bedouin Star-Lore in Sinai and the Negev |journal=Bulletin of the School of Oriental and African Studies, University of London |volume=37 |issue=3 |pages=580–96 |type=abstract |doi=10.1017/S0041977X00127491 |jstor=613801|s2cid=131527348 }}</ref> The south [[celestial pole]] can be approximately located using Canopus and another bright star, [[Achernar]], as the three make an [[equilateral triangle]]. Canopus sits on an imaginary line that extends {{DEC|36}} one way to Sirius and {{DEC|37}} to the south celestial pole.<ref>{{Cite book| last1 = Heifetz| first1 = Milton| last2 = Tirion| first2 = Wil| title = A Walk Through the Heavens: A Guide to Stars and Constellations and Their Legends | date = 2007| publisher = [[Cambridge University Press]]| location = Cambridge | page = 38 | isbn=978-1-139-46138-2}}</ref> Canopus's brightness and location well off the [[ecliptic]] make it useful for space navigation. Many spacecraft carry a special camera known as a "Canopus [[star tracker|Star Tracker]]" plus a Sun sensor for [[Orientation (geometry)|attitude]] determination. [[Mariner 4]] used Canopus for [[Spin-stabilisation|second axis stabilisation]] (after locking on the Sun) in 1964, the first time a star had been used.<ref>{{cite book |last1=United States. National Aeronautics and Space Administration. Scientific and Technical Information Division |title=Astronautics and Aeronautics, 1964: Chronology on Science, Technology and Policy |date=1965 |publisher=Scientific and Technical Information Division, National Aeronautics and Space Administration |page=398 |url=https://books.google.com/books?id=ckkCAAAAIAAJ&pg=PA398}}</ref> ==Spectrum== Canopus was little-studied by western scientists before the 20th century. It was given a spectral class of F in 1897, an early use of this extension to [[Secchi class]] I, applied to those stars where the hydrogen lines are relatively weak and the [[calcium K line]] relatively strong.<ref>{{cite journal |bibcode=1897ApJ.....6..349P |title=Spectra of bright southern stars |last1=Pickering |first1=E. C. |last2=Cannon |first2=A. J. |journal=The Astrophysical Journal |year=1897 |volume=6 |page=349 |doi=10.1086/140407 }}</ref> It was given as a standard star of F0 in the [[Henry Draper Catalogue]], with the spectral type F0 described as having hydrogen lines half the strength of an A0 star and the calcium K line three times as strong as Hδ.<ref name=hd>{{cite journal |bibcode=1918AnHar..92....1C |title=The Henry Draper catalogue : 4h, 5h and 6h |last1=Cannon |first1=Annie Jump |last2=Pickering |first2=Edward Charles |journal=Annals of Harvard College Observatory |year=1918 |volume=92 |page=1 }}</ref> American astronomer [[Jesse L. Greenstein|Jesse Greenstein]] was interested in stellar spectra and used the newly built [[Otto Struve Telescope]] at [[McDonald Observatory]] to analyze the star's spectrum in detail.<ref>{{cite book |last1=Trimble |first1=Virginia | first2= Thomas R. |last2=Williams | first3= Katherine | last3=Bracher| first4= Richard | last4=Jarrell| first5=Jordan D.| last5= Marché| first6=F. Jamil | last6=Ragep |title=Biographical Encyclopedia of Astronomers |date=2007 |publisher=Springer Science & Business Media |location=New York, New York |isbn=978-0-387-30400-7 |page=438 |url=https://books.google.com/books?id=t-BF1CHkc50C&pg=PA438}}</ref> In a 1942 paper, he reported that the spectrum is dominated by strong broad hydrogen lines. There are also [[absorption line]]s of carbon, nitrogen, oxygen, sulphur, iron, and many ionised metals.<ref name=greenstein1942>{{cite journal |bibcode=1942ApJ....95..161G |title=The Spectrum of α Carinae |last1=Greenstein |first1=Jesse L. |journal=The Astrophysical Journal |year=1942 |volume=95 |page=161 |doi=10.1086/144382 }}</ref> It was studied in the [[ultraviolet]] by an early astronomical satellite, [[Gemini XI]] in 1966. The UV spectra were considered to be consistent with an F0 [[Supergiant star|supergiant]] having a temperature of {{val|6,900|fmt=commas|u=K}}, the accepted parameters for Canopus at the time.<ref name=kondo1970>{{cite journal |bibcode=1970ApJ...159..927K |title=Ultraviolet Spectrophotometry of Canopus from Gemini XI |last1=Kondo |first1=Y. |last2=Henize |first2=K. G. |last3=Kotila |first3=C. L. |journal=The Astrophysical Journal |year=1970 |volume=159 |page=927 |doi=10.1086/150370 }}</ref> New Zealand-based astronomers [[John Hearnshaw]] and Krishna Desikachary examined the spectrum in greater detail, publishing their results in 1982.<ref>{{cite journal |title=The spectrum of Canopus | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 198 | year= 1982 | issue= 2 | pages= 311–320 | doi= 10.1093/mnras/198.2.311 | bibcode=1982MNRAS.198..311H| doi-access= free }}</ref><ref>{{cite journal |title=The spectrum of Canopus II - Analysis and composition | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 201 | year= 1982 | issue= 3 | pages= 707–721 | doi= 10.1093/mnras/201.3.707 | bibcode=1982MNRAS.201..707D| doi-access= free }}</ref> When [[luminosity class]]es were added to the MK spectral classification scheme, Canopus was assigned class Iab indicating an intermediate luminosity supergiant. This was based on the relative strengths of certain spectral lines understood to be sensitive to the luminosity of a star.<ref name=devaucoleurs>{{cite journal|title=Spectral types and luminosities of B, A and F southern stars|author=de Vaucouleurs, A.|journal=Monthly Notices of the Royal Astronomical Society|volume=117|page=449|date=1957|issue=4|bibcode=1957MNRAS.117..449D|doi=10.1093/mnras/117.4.449|doi-access=free}}</ref> In the [[Bright Star Catalogue]] 5th edition it is given the spectral class F0II, the luminosity class indicating a [[bright giant]].<ref name=bsc>{{cite book |bibcode=1991bsc..book.....H |year=1991 |title=The Bright star catalogue |last1=Hoffleit |first1=Dorrit |last2=Jaschek |first2=Carlos }}</ref> [[Balmer line]] profiles and oxygen line strengths indicate the size and luminosity of Canopus.<ref name=kovtyukh2012>{{cite journal |bibcode=2012MNRAS.423.3268K |title=Accurate luminosities from the oxygen λ7771-4 Å triplet and the fundamental parameters of F-G supergiants |last1=Kovtyukh |first1=V. V. |last2=Gorlova |first2=N. I. |last3=Belik |first3=S. I. |journal=Monthly Notices of the Royal Astronomical Society |year=2012 |volume=423 |issue=4 |page=3268 |doi=10.1111/j.1365-2966.2012.21117.x |arxiv=1204.4115 |s2cid=118683158 }}</ref> When the effects of stellar rotation speed on spectral lines are accounted for, the MK spectral class of Canopus is adjusted to A9II.<ref name=perkins/> Its spectrum consists mostly of absorption lines on a visible [[continuous spectrum|continuum]], but some emission has been detected. For example, the [[calcium K line]] have weak emission wings on each side of the strong central absorption line, first observed in 1966. The emission line profiles are usually correlated with the luminosity of the star as described by the [[Wilson-Bappu effect]], but in the case of Canopus they indicate a luminosity much lower than that calculated by other methods.<ref name=warner1966>{{cite journal|title=CA II emission in the spectrum of Canopus|journal=The Observatory |volume=86 |pages=82|date=April 1966|last=Warner |first=B. |bibcode=1966Obs....86...82W }}</ref> More detailed observations have shown that the emission line profiles are variable and may be due to [[plage (astronomy)|plage]] areas on the surface of the star. Emission can also be found in other lines such as the h and k lines of ionised magnesium.<ref name=bappu1984>{{cite journal |bibcode=1984BASI...12..196B |title=CA II K emission in Canopus |last1=Bappu |first1=M. K. V. |last2=Mekkaden |first2=M. V. |last3=Rao |first3=N. K. |journal=Bulletin of the Astronomical Society of India |year=1984 |volume=12 |page=196 }}</ref> ==Distance== Before the launch of the [[Hipparcos]] satellite telescope, distance estimates for Canopus varied widely, from 96 [[light-year]]s to 1200 light-years. The closer distance was derived from parallax measurements of around {{val|33|ul=mas}}.<ref name=vandekamp1943>{{cite journal |title=Note on the Parallax of Canopus|journal=Popular Astronomy |volume=51 |date=1943 |page=172 |last=van de Kamp |first=Peter|bibcode=1943PA.....51..172V }}</ref> The larger distance derives from the assumption of a very bright [[absolute magnitude]] for Canopus.<ref name=vanzyl>{{cite book|author=J.E. van Zyl|title=Unveiling the Universe: An Introduction to Astronomy|url=https://books.google.com/books?id=Cj7uBwAAQBAJ&pg=PA184|date=6 December 2012|publisher=Springer Science & Business Media|isbn=978-1-4471-1037-8|pages=184–}}</ref> Hipparcos established Canopus as being {{val|310|u=light-years}} ({{val|95|ul=parsecs}}) from the [[Solar System]]; this is based on its 2007 [[parallax]] measurement of {{Val|10.43|0.53|ul=mas}}.<ref name="van Leeuwen2007"/> At 95 parsecs, the [[interstellar extinction]] for Canopus is low at 0.26 magnitudes.<ref name=DomicianoDeSouza/> Canopus is too bright to be included in the normal observation runs of the [[Gaia satellite]] and there is no published Gaia parallax for it.<ref name=dr2>{{cite DR2}}</ref> At present the star is drifting further away from the Sun with a [[radial velocity]] of 20&nbsp;km/s. Some 3.1&nbsp;million years ago it made the closest approach to the Sun at a distance of about {{convert|52.87|pc|ly|0|adj=ri0|order=flip|abbr=on|lk=off}}. Canopus is orbiting the Milky Way with a heliocentric velocity of 24.5&nbsp;km/s and a low [[orbital eccentricity|eccentricity]] of 0.065.<ref name=Anderson2012>{{citation | last1=Anderson | first1=E. | last2=Francis | first2=Ch. | title=XHIP: An extended hipparcos compilation | journal=Astronomy Letters | volume=38 | issue=5 | pages=331 | year=2012 | bibcode=2012AstL...38..331A | arxiv=1108.4971 | doi=10.1134/S1063773712050015 | s2cid=119257644 | postscript=. }}</ref> ==Physical characteristics== [[File:Constellation_Carina.jpg|thumb|right|upright|Canopus is the brightest star in the constellation of Carina (top).]] The [[absorption line]]s in the spectrum of Canopus shift slightly with a period of {{val|6.9|u=days}}. This was first detected in 1906 and the [[doppler effect|Doppler]] variations were interpreted as orbital motion.<ref name=curtis1907>{{cite journal |bibcode=1907PASP...19R.259C |title=The orbits of the spectroscopic binaries alpha Carinae, kappa Velorum, and alpha Pavonis |last1=Curtis |first1=H. D. |journal=Publications of the Astronomical Society of the Pacific |year=1907 |volume=19 |page=259 |doi=10.1086/121781 }}</ref> An orbit was even calculated, but no such companion exists and the small radial velocity changes are due to movements in the atmosphere of the star. The maximum observed [[radial velocities]] are only 0.7 to {{val|1.6|ul=km/s}}. Canopus also has a magnetic field that varies with the same period, detected by the [[Zeeman splitting]] of its spectral lines.<ref name=weiss1986>{{cite journal |bibcode=1986A&A...160..243W | title=The magnetic field of Canopus | last=Weiss | first=W. W. | journal= Astronomy and Astrophysics |volume= 160|pages= 243–250 | year=1986}}</ref> Canopus is bright at [[microwave]] wavelengths, one of the few F-class stars to be detected by radio.<ref name=gudel2002>{{cite journal |bibcode=2002ARA&A..40..217G |title=Stellar Radio Astronomy: Probing Stellar Atmospheres from Protostars to Giants |last1=Güdel |first1=Manuel |journal=Annual Review of Astronomy and Astrophysics |year=2002 |volume=40 |pages=217–261 |doi=10.1146/annurev.astro.40.060401.093806 |arxiv=astro-ph/0206436 |s2cid=53633983 }}</ref> The [[rotation period]] of the star is not accurately known, but may be over three hundred days.<ref name=Testa2004>{{cite journal | title=The Density of Coronal Plasma in Active Stellar Coronae | last1=Testa | first1=Paola | last2=Drake | first2=Jeremy J. | last3=Peres | first3=Giovanni | journal=The Astrophysical Journal | volume=617 | issue=1 | pages=508–530 | date=December 2004 | doi=10.1086/422355 | arxiv=astro-ph/0405019 | bibcode=2004ApJ...617..508T | s2cid=17532089 }}</ref> The [[projected rotational velocity]] has been measured at 9&nbsp;km/s.<ref name=ayres2018/> An early [[Interferometry|interferometric]] measurement of its [[angular diameter]] in 1968 gave a [[Limb darkening|limb-darkened]] value of {{val|6.86|ul=mas}}, close to the accepted modern value.<ref>{{cite journal |bibcode=1968ARA&A...6...13B |title=Measurement of Stellar Diameters |last1=Brown |first1=R. Hanbury |journal=Annual Review of Astronomy and Astrophysics |year=1968 |volume=6 |page=13 |doi=10.1146/annurev.aa.06.090168.000305 }}</ref> [[Very-long-baseline interferometry]] has been used to calculate Canopus' angular diameter at {{val|6.9|ul=mas}}. Combined with distance calculated from its Hipparcos parallax, this gives it a radius of 71 times [[Solar radius|that of the Sun]].<ref name=vlti/> If it were at the centre of the Solar System, it would extend 90% of the way to the orbit of [[Mercury (planet)|Mercury]].<ref name=Kalerstars>{{cite web|url=http://stars.astro.illinois.edu/sow/canopus.html|title=Canopus|last=Kaler|first=Jim|work=Stars|publisher=University of Illinois|access-date=8 July 2012|date=26 June 2009}}</ref> The radius and temperature relative to the Sun means that it is 10,700 times more luminous than the Sun, and its position in the [[H-R diagram]] relative to theoretical [[stellar evolution|evolutionary]] tracks means that it is {{Val|8.0|0.3}} times as massive as the Sun.<ref name=vlti/> Measurements of its shape find a 1.1° departure from spherical symmetry.<ref name=cruzalebes2015>{{cite journal |bibcode=2015MNRAS.446.3277C |title=Departure from centrosymmetry of red giants and supergiants measured with VLTI/AMBER |last1=Cruzalèbes |first1=P. |last2=Jorissen |first2=A. |last3=Chiavassa |first3=A. |last4=Paladini |first4=C. |last5=Rabbia |first5=Y. |last6=Spang |first6=A. |journal=Monthly Notices of the Royal Astronomical Society |year=2015 |volume=446 |issue=4 |page=3277 |doi=10.1093/mnras/stu2382 |doi-access=free }}</ref> Canopus is a source of [[X-ray astronomy|X-rays]], which are probably produced by its corona, magnetically heated to several million [[Kelvin]]. The temperature has likely been stimulated by fast rotation combined with strong convection percolating through the star's outer layers.<ref name=ness>{{cite journal|bibcode=2004A&A...427..667N|title=On the sizes of stellar X-ray coronae|journal=Astronomy and Astrophysics|volume=427|issue=2|pages=667–683|last1=Ness|first1=J.-U.|last2=Güdel|first2=M.|last3=Schmitt|first3=J. H. M. M.|last4=Audard|first4=M.|last5=Telleschi|first5=A.|year=2004|doi=10.1051/0004-6361:20040504|arxiv = astro-ph/0407231 |s2cid=11468731}}</ref> The soft X-ray sub-coronal X-ray emission is much weaker than the hard X-ray coronal emission. The same behaviour has been measured in other F-class supergiants such as [[α Persei]] and is now believed to be a normal property of such stars.<ref name=ayres2018/> == Evolution == The spectrum of Canopus indicates that it has exhausted its core hydrogen and [[stellar evolution|evolved]] away from the [[main sequence]], where it spent some 30 million years of its existence as a blue-white star <!-- source suggests B2V but may be too exact --> of around 10 solar masses.<ref>{{cite journal |last1=Peimbert |first1=M. |last2=Wallerstein | first2= G.| last3= Pilachowski | first3= C. A. |title=An upper limit for the deuterium abundance in Canopus |journal=Astronomy and Astrophysics |date=1981 |volume=104 |issue=1 |pages=72–74 | bibcode=1981A&A...104...72P}}</ref> The position of Canopus in the [[H–R diagram]] indicates that it is currently in the core-helium burning phase.<ref name=vlti/> It is an intermediate mass star that has left the [[red-giant branch]] before its core became [[degenerate matter|degenerate]] and is now in a [[blue loop]].<ref name=desouza>{{Cite journal | last1 = Domiciano De Souza | first1 = A. | last2 = Bendjoya | first2 = P. | last3 = Vakili | first3 = F. | last4 = Millour | first4 = F. | last5 = Petrov | first5 = R. G. | title = Diameter and photospheric structures of Canopus from AMBER/VLTI interferometry | doi = 10.1051/0004-6361:200810450 | journal = Astronomy and Astrophysics | volume = 489 | issue = 2 | pages = L5–L8 | year = 2008 |bibcode = 2008A&A...489L...5D | url = https://hal.archives-ouvertes.fr/hal-00316994/document | doi-access = free }}</ref> Models of stellar evolution in the blue loop phase show that the length of the blue loop is strongly affected by rotation and mixing effects inside the star. It is difficult to determine whether a star is currently evolving towards hotter temperature or returning to cooler temperatures, since the evolutionary tracks for stars with different masses overlap during the blue loops.<ref name=smiljanic2006>{{cite journal |bibcode=2006A&A...449..655S |title=CNO in evolved intermediate mass stars |last1=Smiljanic |first1=R. |last2=Barbuy |first2=B. |last3=De Medeiros |first3=J. R. |last4=Maeder |first4=A. |journal=Astronomy and Astrophysics |year=2006 |volume=449 |issue=2 |page=655 |doi=10.1051/0004-6361:20054377 |arxiv=astro-ph/0511329 |s2cid=3711409 }}</ref> Canopus lies on the warm side of the [[instability strip]] and does not pulsate like [[Cepheid variables]] of a similar luminosity.<ref name=ayres2011>{{cite journal |doi=10.1088/0004-637X/738/2/120 |title=The Curious Case of the Alpha Persei Corona: A Dwarf in Supergiant's Clothing? |year=2011 |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |volume=738 |issue=2 |page=120 |bibcode=2011ApJ...738..120A |doi-access=free }}</ref> However its atmosphere does appear to be unstable, showing strong signs of convection.<ref name=smiljanic2006/> Canopus may not be massive enough for its [[nuclear fusion|fusion]] chain to reach iron and trigger a core collapse and subsequent [[supernova]], instead eventually becoming a neon-oxygen [[white dwarf]].<ref name=Kalerstars/> ==Cultural significance == Canopus was known to the ancient Mesopotamians and given the name ''NUN-ki'' and represented the city of [[Eridu]] in the ''Three Stars Each'' [[Babylonian star catalogues]] and later [[MUL.APIN]] around 1100 BC.<ref>{{cite journal | last = Rogers | first = John H. | date = 1998 | title = Origins of the Ancient Constellations: I. The Mesopotamian Traditions | journal = Journal of the British Astronomical Association | volume = 108 | issue = 1 | pages = 9–28 | bibcode = 1998JBAA..108....9R}}</ref> Today, the star [[Sigma Sagittarii]] is known by the common name Nunki.<ref name=allen>{{citation | page=359 | first1=Richard Hinckley | last1=Allen | title=Star Names, their lore and meaning}}</ref> Canopus was not visible to the mainland [[Ancient Greece|ancient Greeks]] and [[Roman Empire|Romans]]; it was, however, visible to the [[ancient Egypt]]ians.<ref name="Schaaf107">Schaaf, p. 107.</ref> Hence [[Aratus]] did not write of the star as it remained below the horizon, while [[Eratosthenes]] and [[Ptolemy]]—observing from [[Alexandria]]—did, calling it ''Kanōbos''.<ref name=ridpathCr>{{cite web| url=http://www.ianridpath.com/startales/carina.htm | title=Carina |last1=Ridpath|first1=Ian|publisher=self-published |work=Star Tales | access-date= 10 December 2015}}</ref> An [[Egypt]]ian priestly poet in the time of [[Thutmose III]] mentions the star as ''Karbana,'' "the star which pours his light in a glance of fire, when he disperses the morning dew."<ref name="hinkley63" /> Under the [[Ptolemies]], the star was known as ''Ptolemaion'' ([[Ancient Greek|Greek]]: Πτολεμαῖον) and its [[acronychal rising]] marked the date of the Ptolemaia festival, which was held every four years, from 262 to 145 BC.<ref>[[Martianus Capella]] 7.838, {{cite journal | last1 = Hazzard | last2 = Fitzgerald | year = 1991 | title = The Regulation of the Ptolemeia | journal = Journal of the Royal Astronomical Society of Canada | volume = 85 | pages = 6–23 |bibcode = 1991JRASC..85....6H }}; Hazzard. 2000. ''Imagination of a Monarchy: Studies in Ptolemaic Propaganda'', 34–36.</ref> [[File:Statue of Averroes in Córdoba, Spain.jpg|thumb|upright|[[Averroes]], who used his 1153 observation of Canopus in [[Marrakesh]] while the star was invisible in his native Spain as an argument that the [[Spherical Earth|earth is round]].<ref name=ibn_rushd/>]] ===India=== In Indian [[Vedas|Vedic literature]], Canopus is associated with the sage [[Agastya]], one of the ancient [[siddhar]]s and [[rishi]]s (the others are associated with the stars of the [[Big Dipper]]).<ref name="Frawley 1993">{{cite book|last=Frawley|first=David|title=Gods, Sages and Kings: Vedic Secrets of Ancient Civilization|publisher=Motilal Banarsidass |location=New Delhi, India|date=1993}}</ref> To Agastya, the star is said to be the 'cleanser of waters', and its rising coincides with the calming of the waters of the [[Indian Ocean]]. It is thus considered the son of [[Pulastya]], son of [[Brahma]]. Canopus is described by [[Pliny the Elder]] and [[Gaius Julius Solinus]] as the largest, brightest and only source of [[starlight]] for navigators near [[Tamraparni]] island (ancient Sri Lanka) during many nights.<ref>{{cite book |last1=Pridham |first1=Charles |title=An Historical, Political, and Statistical Account of Ceylon and Its Dependencies |date=1849 |publisher=T. and W. Boone |page=7 |url=https://books.google.com/books?id=O4aqHOMSJdYC&pg=PR19-IA5|language=en}}</ref><ref name="Frawley 1993"/><ref>{{cite book |last1=Elder |first1=Pliny the |title=Delphi Complete Works of Pliny the Elder (Illustrated) |date=2015 |publisher=Delphi Classics |url=https://books.google.com/books?id=OrJ0CgAAQBAJ&pg=PA343|language=en}}</ref> ===China=== Canopus was described as Shou Xing, the Star of Longevity, in the ''Shiji'' ([[Records of the Grand Historian]]) completed in 94 BC by Chinese historian [[Sima Qian]].<ref name=fong83>{{cite journal | title=The Iconography of the Popular Gods of Happiness, Emolument, and Longevity (Fu Lu Shou) | first=Mary H. |last=Fong | journal=Artibus Asiae | volume= 44 | issue= 2/3 | year=1983| pages= 159–199 | doi= 10.2307/3249596| jstor=3249596 }}</ref> Drawing on sources from the [[Warring States period]], he noted it to be the southern counterpart of [[Sirius]],<ref name="IDP"/> and wrote of a sanctuary dedicated to it established by Emperor [[Qin Shi Huang]] between 221 and 210 BC. During the [[Han dynasty]], the star was auspicious, its appearance in the southern sky heralding peace and absence war.<ref name=fong83/> From the imperial capital [[Chang'an]], the star made a low transit across the southern sky, indicating true south to observers, and was often obscured by clouds.<ref name=baumann19>{{cite journal | title=The White Old Man: Géluk-Mongolian Canopus Allegory and the Existence of God | first=Brian | last=Baumann | journal= Central Asiatic Journal | volume= 62 | issue= 1 | year=2019| pages= 35–68 | doi=10.13173/centasiaj.62.1.0035| s2cid=213083544 }}</ref> During this time it was also equated with [[Old Man of the South Pole]] (in {{zh|c=南极老人|p=Nanji Lǎorén}})<ref name=fong83/> Under this name, Canopus appears (albeit misplaced northwards) on the medieval Chinese manuscript the [[Dunhuang Star Chart]], although it cannot be seen from the Chinese capital of [[Chang'an]].<ref name="IDP">{{cite journal|bibcode=2009JAHH...12...39B|arxiv=0906.3034|title=The Dunhuang Sky: A Comprehensive Study of the Oldest Known Star Atlas|volume=12|issue=1|pages=39–59|last1=Bonnet-Bidaud|first1=Jean-Marc |last2=Praderie|first2=Françoise |last3=Whitfield|first3=Susan |author-link=Susan Whitfield |journal=The International Dunhuang Project: The Silk Road Online|year=2009}}</ref> The Chinese astronomer [[Yi Xing]] had journeyed south to chart Canopus and other far southern stars in 724 AD.<ref>{{cite book|last=Needham|first=Joseph|title=Science and Civilisation in China: Volume 3, Mathematics and the Sciences of the Heavens and the Earth|publisher=Cambridge University Press|location=Cambridge, United Kingdom|date=1959|pages=274|isbn=0521058015}}</ref> Its personification as the Old Man Star was popularised in the [[Tang Dynasty]], where it appeared often in poetry and memorials. Later still, during the [[Ming Dynasty]], the star was established as one of the [[Sanxing (deities)|Three Stars]] (Fu Lo Shou), appearing frequently in art and literature of the time.<ref name=fong83/> This symbolism spread into neighbouring cultures in Asia.<ref name=baumann19/> In Japan, Canopus is known as ''Mera-boshi'' and ''Roujin-sei'' (the old man star),<ref>{{cite conference |url=http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |title=Stellar Iconology and Astronomical Folklore in Japan |author=Takao Ibaraki |book-title=International Planetarium Society (IPS) Conferences 1996 |publisher=International Planetarium Society |location=Osaka |date=14 July 1996 |access-date=25 February 2012 |url-status=dead |archive-url=https://web.archive.org/web/20120326195757/http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |archive-date=2012-03-26 }}</ref> and in Mongolia, it was personified as the White Old Man.<ref name=fong83/> Although the link was known in Tibet, with names such as ''Genpo karpo'' (''Rgan po dkar po'') or ''Genkar'' (''Rgan dkar'') "White Old Man", the symbolism was not popular. Instead, Canopus was more commonly named ''Karma Rishi སྐར་མ་རི་ཥི།'', derived from Indian mythology. Tibetans celebrated the star's heliacal rising with ritual bathing and associated it with morning dew.<ref name=baumann19/> ===Polynesia=== Bright stars were important to the ancient [[Polynesian culture|Polynesians]] for navigation between the many islands and atolls of the Pacific Ocean. Low on the horizon, they acted as stellar compasses to assist mariners in charting courses to particular destinations. Canopus served as the southern wingtip of a "Great Bird" constellation called ''Manu'', with Sirius as the body and [[Procyon]] the northern wingtip, which divided the Polynesian night sky into two hemispheres.<ref name="Holberg">{{cite book | last=Holberg | first=J.B. | title=Sirius: Brightest Diamond in the Night Sky | date=2007 | publisher=Praxis Publishing | location=Chichester, UK | isbn=978-0-387-48941-4 | pages=[https://archive.org/details/siriusbrightestd0000holb/page/25 25–26] | url=https://archive.org/details/siriusbrightestd0000holb/page/25 }}</ref> The [[Hawaiian people]] called Canopus ''Ke Alii-o-kona-i-ka-lewa'', "The chief of the southern expanse"; it was one of the stars used by [[Hawaiʻiloa]] and Ki when they traveled to the [[Southern Ocean]].{{sfn|Makemson|1941|p=198}} The [[Māori people]] of [[New Zealand|New Zealand/Aotearoa]] had several names for Canopus. ''[[Ariki]]'' ("High-born"), was known as a solitary star that appeared in the east, prompting people to weep and chant.{{sfn|Makemson|1941|p=201}} They also named it ''[[Atutahi]]'', ''Aotahi'' or ''Atuatahi'', "Stand Alone".<ref>p. 419, [https://books.google.com/books?id=p7dR2w1Wv2sC ''Mythology: Myths, Legends and Fantasies''], Janet Parker, Alice Mills, Julie Stanton, Durban, Struik Publishers, 2007.</ref> Its solitary nature indicates it is a ''[[Tapu (Polynesian culture)|tapu]]'' star, as ''tapu'' people are often solitary. Its appearance at the beginning of the ''Maruaroa'' season foretells the coming winter; light rays to the south indicate a cold wet winter, and to the north foretell a mild winter. Food was offered to the star on its appearance.<ref name="Best22">{{cite book|last=Best|first=Elsdon|title=Astronomical Knowledge of the Maori: Genuine and Empirical|publisher=Dominion Museum|location=Wellington, New Zealand|date=1922|pages=34–35|url=http://nzetc.victoria.ac.nz/tm/scholarly/tei-BesAstro-t1-body-d1-d6-d4.html}}</ref> This name has several mythologies attached to it. One story tells of how Atutahi was left outside the basket representing the [[Milky Way]] when [[Tāne]] wove it. Another related myth about the star says that Atutahi was the first-born child of [[Rangi and Papa|Rangi]], who refused to enter the Milky Way and so turned it sideways and rose before it. The same name is used for other stars and constellations throughout Polynesia.{{sfn|Makemson|1941|pp=200–202}} ''Kapae-poto'', "Short horizon", referred to it rarely setting as seen in New Zealand;{{sfn|Makemson|1941|p=217}} ''Kauanga'' ("Solitary") was the name for Canopus only when it was the last star visible before sunrise.{{sfn|Makemson|1941|p=218}} The people of the [[Society Islands]] had two names for Canopus, as did the [[Tuamotu]] people. The Society Islanders called Canopus ''Taurua-e-tupu-tai-nanu'', "Festivity-whence-comes-the-flux-of-the-sea", and ''Taurua-nui-o-te-hiti-apatoa'' "Great-festivity-of-the-border-of-the-south",{{sfn|Makemson|1941|p=259}} and the Tuamotu people called the star ''Te Tau-rari'' and ''Marere-te-tavahi'', the latter said to be the true name for the former, "He-who-stands-alone".{{sfn|Makemson|1941|p=229}} ===Africa=== In the [[Guanches|Guanche]] mythology of the island of [[Tenerife]] (Spain), the star Canopus was linked with the goddess [[Chaxiraxi]].<ref name="Rumeu">{{cite book|author=Antonio Rumeu de Armas|title=La conquista de Tenerife, 1494–1496|url=https://books.google.com/books?id=Ck4BAAAAMAAJ|year=1975|publisher=Aula de Cultura de Tenerife|isbn=9788450071078}}</ref> The [[Tswana people]] of [[Botswana]] knew Canopus as ''Naka''. Appearing late in winter skies, it heralded increasing winds and a time when trees lose their leaves. Stock owners knew it was time to put their sheep with rams.<ref>{{cite journal|last=Clegg|first=Andrew|date=1986|title=Some Aspects of Tswana Cosmology|journal=Botswana Notes and Records|volume=18|pages=33–37|jstor=40979758 }}</ref> In southern Africa, the Sotho, Tswana and Venda people called Canopus ''Naka'' or ''Nanga'', “the Horn Star”, while the Zulu and Swazi called it ''inKhwenkwezi'' "Brilliant star". It appears in the predawn sky in the third week of May. According to the Venda, the first person to see Canopus would blow a ''phalaphala'' horn from the top of a hill, getting a cow for a reward. The Sotho chiefs also awarded a cow, and ordered their medicine men to roll bone dice and read the fortune for the coming year.<ref name=snedegar95>{{cite journal |last1=Snedegar |first1=K.V. |title=Stars and seasons in Southern Africa |journal=Vistas in Astronomy |date=1995 |volume=39 |issue=4 |pages=529–38 |doi=10.1016/0083-6656(95)00008-9|bibcode=1995VA.....39..529S }}</ref> To the [[ǀXam language|ǀXam]]-speaking [[Bushmen]] of South Africa, Canopus and Sirius signalled the appearance of termites and flying ants. They also believed that stars had the power to cause death and misfortune, and they would pray to [[Sirius]] and Canopus in particular to impart good fortune or skill.<ref>{{cite journal| title="The Sky's Things", <nowiki>|</nowiki>xam Bushman 'Astrological Mythology' as recorded in the Bleek and Lloyd Manuscripts |last1=Hollman|first1=J. C.|journal=African Sky|volume= 11|page=8 |bibcode=2007AfrSk..11....8H|year = 2007 }}</ref> The [[ǃKung people]] of the [[Kalahari Desert]] in Botswana held Canopus and Capella to be the horns of ''tshxum'' (the Pleiades), the appearance of all three marking the end of the dry season and start of the rainy season.<ref>{{cite journal |last1=Marshall |first1=Lorna |title=Two Ju/ wa constellations |journal=Botswana Notes & Records |date=1975 |volume=7 |issue=1 |pages=153–159 | issn=0525-5090 |url=https://journals.co.za/docserver/fulltext/botnotes/7/1/548.pdf?expires=1590793041&id=id&accname=guest&checksum=3204085F9555AD9D083799E1F38E3AED}}</ref> ===Americas=== The [[Navajo]] observed the star and named it ''Maʼii Bizòʼ'', the “Coyote Star”. According to legend, Maʼii (Coyote) took part in the naming and placing of the star constellations during the creation of the universe. He placed Canopus directly south, naming it after himself.<ref name="Maryboy">Maryboy, Nancy D. (2004). ''A Guide to Navajo Astronomy.'' Indigenous Education Institute : Bluff, Utah.</ref> The [[Kalapalo]] people of [[Mato Grosso]] state in Brazil saw Canopus and [[Procyon]] as ''Kofongo'' "Duck", with [[Castor (star)|Castor]] and [[Pollux (star)|Pollux]] representing his hands. The asterism's appearance signified the coming of the rainy season and increase in [[manioc]], a food staple fed to guests at feasts.<ref name="basso87">{{cite book|last=Basso|first=Ellen B. |title=In Favor of Deceit: A Study of Tricksters in an Amazonian Society|publisher=University of Arizona Press|location=Tucson, Arizona|date=1987|page=[https://archive.org/details/infavorofdeceits0000bass/page/360 360]|isbn=0816510229|url=https://archive.org/details/infavorofdeceits0000bass|url-access=registration}}</ref> ===Australia=== Canopus is identified as the moiety ancestor ''Waa'' "Crow" to some [[Koori]] people in southeastern Australia.<ref>{{cite book|last=Mudrooroo|title=Aboriginal mythology: an A-Z spanning the history of aboriginal mythology from the earliest legends to the present day|publisher=HarperCollins|location=London|date=1994|page=27|isbn=1-85538-306-3}}</ref> The Boorong people of northwestern Victoria recalled that ''War'' (Canopus) was the brother of ''Warepil'' (Sirius), and that he brought fire from the heavens and introduced it to humanity. His wife was ''Collowgullouric War'' ([[Eta Carinae]]).<ref name=hamacher10>{{cite journal|last1=Hamacher|first1=Duane W. |last2=Frew|first2=David J. |date=2010|title= An Aboriginal Australian Record of the Great Eruption of Eta Carinae|journal=Journal of Astronomical History & Heritage |volume=13|issue=3|pages= 220–34|bibcode=2010JAHH...13..220H|arxiv = 1010.4610 }}</ref> The Pirt-Kopan-noot people of western Victoria tell of ''Waa'' "Crow" falling in love with a queen, ''Gneeanggar'' "Wedge-tailed Eagle" (Sirius) and her six attendants (the Pleiades). His advances spurned, he hears that the women are foraging for grubs and so transforms himself into a grub. When the women dig him out, he changes into a giant and carries her off.<ref>Mudroodoo, p. 55.</ref> The Kulin people know Canopus as ''Lo-an-tuka''.<ref name=hamacher10/> Objects in the sky are also associated with states of being for some tribes; the Wailwun of northern New South Wales know Canopus as ''Wumba'' "deaf", alongside Mars as ''Gumba'' "fat" and Venus as ''Ngindigindoer'' "you are laughing".<ref name="noctuary">{{cite book|last=Johnson|first=Diane|title=Night skies of aboriginal Australia: a noctuary|publisher=University of Sydney|location=Darlington, New South Wales|date=1998|page=[https://archive.org/details/nightskiesofabor0000john/page/84 84]|isbn=1-86451-356-X|url-access=registration|url=https://archive.org/details/nightskiesofabor0000john/page/84}}</ref> Tasmanian aboriginal lore holds that Canopus is ''Dromerdene'', the brother of ''Moinee''; the two fought and fell out of the sky, with ''Dromerdene'' falling into Louisa Bay in southwest Tasmania.<ref name="haynes2000">{{cite book|last=Haynes|first=Ros D.|title= Astronomy and the Dreaming: The Astronomy of the Aboriginal Australians. Astronomy Across Cultures: The History of Non-Western Astronomy|publisher=Kluwer Academic Publishers|date=2000|page=57|doi=10.1007/978-94-011-4179-6_3}}</ref> ===Legacy=== [[File:HMS Glory LOC ggbain.17135.jpg|thumb|right|[[Canopus-class battleship]] HMS Glory]] Canopus appears on the [[flag of Brazil]], symbolising the state of [[Goiás]].<ref>{{cite web |title=Astronomy of the Brazilian Flag |url=https://flagspot.net/flags/br_astro.html |publisher=FOTW Flags Of The World website }}</ref> Two U.S. Navy [[submarine tender]]s have been named after Canopus, the [[USS Canopus (AS-9)|first]] serving from 1922 to 1942 and the [[USS Canopus (AS-34)|second]] serving from 1965 to 1994. The [[Royal Navy]] built nine [[Canopus-class ship of the line|Canopus-class ships of the line]] in the early 19th century, and six {{Sclass|Canopus|battleship|1}}s which entered services between 1899 and 1902. There are at least two mountains named after the star: [[Mount Canopus]] in Antarctica; and Mount Canopus or Canopus Hill in [[Tasmania]], the location of the [[Canopus Hill Observatory|Canopus Hill astronomical observatory]]. {{clear}} ==See also== *[[List of brightest stars]] *[[List of most luminous stars]] *[[Dune (novel)]] ==References== {{Reflist|30em}} ===Bibliography=== * {{cite book | last = Makemson | first = Maud Worcester | date = 1941 | publisher = [[Yale University Press]] | title = The Morning Star Rises: an account of Polynesian astronomy | bibcode = 1941msra.book.....M }} * {{cite book |title=The Brightest Stars: Discovering the Universe through the Sky's Most Brilliant Stars |last=Schaaf |first=Fred |year=2008 |publisher=John Wiley & Sons |location=Hoboken, NJ |isbn=978-0-471-70410-2 }} == External links == {{Sky|06|23|57.1099|-|52|41|44.378|310}} {{Carina (constellation)}} {{Portal bar|Astronomy|Stars|Spaceflight|Outer space|Solar System}} {{Authority control}} {{DEFAULTSORT:Canopus}} [[Category:Canopus| ]] [[Category:Bayer objects|Carinae, Alpha]] [[Category:Carina (constellation)]] [[Category:A-type bright giants]] [[Category:Henry Draper Catalogue objects|045348]] [[Category:Hipparcos objects|030438]] [[Category:Bright Star Catalogue objects|2326]] [[Category:Stars with proper names]] [[Category:Durchmusterung objects]] 3547233edddd3de1b6a9882514b6f145cc63ca57 Template:Nowrap 10 38 92 91 2022-09-04T15:24:25Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <span class="nowrap">{{{1}}}</span><noinclude> {{documentation}} <!-- Categories go on the /doc page; interwikis go to Wikidata. --> </noinclude> 5d0dc6b6d89b37f4356242404f46138a4017f015 Module:Yesno 828 39 94 93 2022-09-04T15:24:26Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- Function allowing for consistent treatment of boolean-like wikitext input. -- It works similarly to the template {{yesno}}. return function (val, default) -- If your wiki uses non-ascii characters for any of "yes", "no", etc., you -- should replace "val:lower()" with "mw.ustring.lower(val)" in the -- following line. val = type(val) == 'string' and val:lower() or val if val == nil then return nil elseif val == true or val == 'yes' or val == 'y' or val == 'true' or val == 't' or val == 'on' or tonumber(val) == 1 then return true elseif val == false or val == 'no' or val == 'n' or val == 'false' or val == 'f' or val == 'off' or tonumber(val) == 0 then return false else return default end end f767643e7d12126d020d88d662a3dd057817b9dc Module:Arguments 828 40 96 95 2022-09-04T15:24:27Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module provides easy processing of arguments passed to Scribunto from -- #invoke. It is intended for use by other Lua modules, and should not be -- called from #invoke directly. local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local arguments = {} -- Generate four different tidyVal functions, so that we don't have to check the -- options every time we call it. local function tidyValDefault(key, val) if type(val) == 'string' then val = val:match('^%s*(.-)%s*$') if val == '' then return nil else return val end else return val end end local function tidyValTrimOnly(key, val) if type(val) == 'string' then return val:match('^%s*(.-)%s*$') else return val end end local function tidyValRemoveBlanksOnly(key, val) if type(val) == 'string' then if val:find('%S') then return val else return nil end else return val end end local function tidyValNoChange(key, val) return val end local function matchesTitle(given, title) local tp = type( given ) return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title end local translate_mt = { __index = function(t, k) return k end } function arguments.getArgs(frame, options) checkType('getArgs', 1, frame, 'table', true) checkType('getArgs', 2, options, 'table', true) frame = frame or {} options = options or {} --[[ -- Set up argument translation. --]] options.translate = options.translate or {} if getmetatable(options.translate) == nil then setmetatable(options.translate, translate_mt) end if options.backtranslate == nil then options.backtranslate = {} for k,v in pairs(options.translate) do options.backtranslate[v] = k end end if options.backtranslate and getmetatable(options.backtranslate) == nil then setmetatable(options.backtranslate, { __index = function(t, k) if options.translate[k] ~= k then return nil else return k end end }) end --[[ -- Get the argument tables. If we were passed a valid frame object, get the -- frame arguments (fargs) and the parent frame arguments (pargs), depending -- on the options set and on the parent frame's availability. If we weren't -- passed a valid frame object, we are being called from another Lua module -- or from the debug console, so assume that we were passed a table of args -- directly, and assign it to a new variable (luaArgs). --]] local fargs, pargs, luaArgs if type(frame.args) == 'table' and type(frame.getParent) == 'function' then if options.wrappers then --[[ -- The wrappers option makes Module:Arguments look up arguments in -- either the frame argument table or the parent argument table, but -- not both. This means that users can use either the #invoke syntax -- or a wrapper template without the loss of performance associated -- with looking arguments up in both the frame and the parent frame. -- Module:Arguments will look up arguments in the parent frame -- if it finds the parent frame's title in options.wrapper; -- otherwise it will look up arguments in the frame object passed -- to getArgs. --]] local parent = frame:getParent() if not parent then fargs = frame.args else local title = parent:getTitle():gsub('/sandbox$', '') local found = false if matchesTitle(options.wrappers, title) then found = true elseif type(options.wrappers) == 'table' then for _,v in pairs(options.wrappers) do if matchesTitle(v, title) then found = true break end end end -- We test for false specifically here so that nil (the default) acts like true. if found or options.frameOnly == false then pargs = parent.args end if not found or options.parentOnly == false then fargs = frame.args end end else -- options.wrapper isn't set, so check the other options. if not options.parentOnly then fargs = frame.args end if not options.frameOnly then local parent = frame:getParent() pargs = parent and parent.args or nil end end if options.parentFirst then fargs, pargs = pargs, fargs end else luaArgs = frame end -- Set the order of precedence of the argument tables. If the variables are -- nil, nothing will be added to the table, which is how we avoid clashes -- between the frame/parent args and the Lua args. local argTables = {fargs} argTables[#argTables + 1] = pargs argTables[#argTables + 1] = luaArgs --[[ -- Generate the tidyVal function. If it has been specified by the user, we -- use that; if not, we choose one of four functions depending on the -- options chosen. This is so that we don't have to call the options table -- every time the function is called. --]] local tidyVal = options.valueFunc if tidyVal then if type(tidyVal) ~= 'function' then error( "bad value assigned to option 'valueFunc'" .. '(function expected, got ' .. type(tidyVal) .. ')', 2 ) end elseif options.trim ~= false then if options.removeBlanks ~= false then tidyVal = tidyValDefault else tidyVal = tidyValTrimOnly end else if options.removeBlanks ~= false then tidyVal = tidyValRemoveBlanksOnly else tidyVal = tidyValNoChange end end --[[ -- Set up the args, metaArgs and nilArgs tables. args will be the one -- accessed from functions, and metaArgs will hold the actual arguments. Nil -- arguments are memoized in nilArgs, and the metatable connects all of them -- together. --]] local args, metaArgs, nilArgs, metatable = {}, {}, {}, {} setmetatable(args, metatable) local function mergeArgs(tables) --[[ -- Accepts multiple tables as input and merges their keys and values -- into one table. If a value is already present it is not overwritten; -- tables listed earlier have precedence. We are also memoizing nil -- values, which can be overwritten if they are 's' (soft). --]] for _, t in ipairs(tables) do for key, val in pairs(t) do if metaArgs[key] == nil and nilArgs[key] ~= 'h' then local tidiedVal = tidyVal(key, val) if tidiedVal == nil then nilArgs[key] = 's' else metaArgs[key] = tidiedVal end end end end end --[[ -- Define metatable behaviour. Arguments are memoized in the metaArgs table, -- and are only fetched from the argument tables once. Fetching arguments -- from the argument tables is the most resource-intensive step in this -- module, so we try and avoid it where possible. For this reason, nil -- arguments are also memoized, in the nilArgs table. Also, we keep a record -- in the metatable of when pairs and ipairs have been called, so we do not -- run pairs and ipairs on the argument tables more than once. We also do -- not run ipairs on fargs and pargs if pairs has already been run, as all -- the arguments will already have been copied over. --]] metatable.__index = function (t, key) --[[ -- Fetches an argument when the args table is indexed. First we check -- to see if the value is memoized, and if not we try and fetch it from -- the argument tables. When we check memoization, we need to check -- metaArgs before nilArgs, as both can be non-nil at the same time. -- If the argument is not present in metaArgs, we also check whether -- pairs has been run yet. If pairs has already been run, we return nil. -- This is because all the arguments will have already been copied into -- metaArgs by the mergeArgs function, meaning that any other arguments -- must be nil. --]] if type(key) == 'string' then key = options.translate[key] end local val = metaArgs[key] if val ~= nil then return val elseif metatable.donePairs or nilArgs[key] then return nil end for _, argTable in ipairs(argTables) do local argTableVal = tidyVal(key, argTable[key]) if argTableVal ~= nil then metaArgs[key] = argTableVal return argTableVal end end nilArgs[key] = 'h' return nil end metatable.__newindex = function (t, key, val) -- This function is called when a module tries to add a new value to the -- args table, or tries to change an existing value. if type(key) == 'string' then key = options.translate[key] end if options.readOnly then error( 'could not write to argument table key "' .. tostring(key) .. '"; the table is read-only', 2 ) elseif options.noOverwrite and args[key] ~= nil then error( 'could not write to argument table key "' .. tostring(key) .. '"; overwriting existing arguments is not permitted', 2 ) elseif val == nil then --[[ -- If the argument is to be overwritten with nil, we need to erase -- the value in metaArgs, so that __index, __pairs and __ipairs do -- not use a previous existing value, if present; and we also need -- to memoize the nil in nilArgs, so that the value isn't looked -- up in the argument tables if it is accessed again. --]] metaArgs[key] = nil nilArgs[key] = 'h' else metaArgs[key] = val end end local function translatenext(invariant) local k, v = next(invariant.t, invariant.k) invariant.k = k if k == nil then return nil elseif type(k) ~= 'string' or not options.backtranslate then return k, v else local backtranslate = options.backtranslate[k] if backtranslate == nil then -- Skip this one. This is a tail call, so this won't cause stack overflow return translatenext(invariant) else return backtranslate, v end end end metatable.__pairs = function () -- Called when pairs is run on the args table. if not metatable.donePairs then mergeArgs(argTables) metatable.donePairs = true end return translatenext, { t = metaArgs } end local function inext(t, i) -- This uses our __index metamethod local v = t[i + 1] if v ~= nil then return i + 1, v end end metatable.__ipairs = function (t) -- Called when ipairs is run on the args table. return inext, t, 0 end return args end return arguments 3134ecce8429b810d445e29eae115e2ae4c36c53 Module:No globals 828 41 98 97 2022-09-04T15:24:27Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local mt = getmetatable(_G) or {} function mt.__index (t, k) if k ~= 'arg' then error('Tried to read nil global ' .. tostring(k), 2) end return nil end function mt.__newindex(t, k, v) if k ~= 'arg' then error('Tried to write global ' .. tostring(k), 2) end rawset(t, k, v) end setmetatable(_G, mt) 8ce3969f7d53b08bd00dabe4cc9780bc6afd412a Template:Val 10 42 100 99 2022-09-04T15:24:28Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{{{{♥|safesubst:}}}#invoke:val|main}}</includeonly><noinclude> {{documentation}} </noinclude> 4765ec60d7235aeb2b778f12eac5cdcbd4ebab5d Module:Val 828 43 102 101 2022-09-04T15:24:29Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- For Template:Val, output a number and optional unit. -- Format options include scientific and uncertainty notations. local numdot = '.' -- decimal mark (use ',' for Italian) local numsep = ',' -- group separator (use ' ' for Italian) local mtext = { -- Message and other text that should be localized. ['mt-bad-exponent'] = 'exponent parameter (<b>e</b>)', ['mt-parameter'] = 'parameter ', ['mt-not-number'] = 'is not a valid number', ['mt-cannot-range'] = 'cannot use a range if the first parameter includes "e"', ['mt-need-range'] = 'needs a range in parameter 2', ['mt-should-range'] = 'should be a range', ['mt-cannot-with-e'] = 'cannot be used if the first parameter includes "e"', ['mt-not-range'] = 'does not accept a range', ['mt-cannot-e'] = 'cannot use e notation', ['mt-too-many-parameter'] = 'too many parameters', ['mt-need-number'] = 'need a number after the last parameter because it is a range.', ['mt-ignore-parameter4'] = 'Val parameter 4 ignored', ['mt-val-not-supported'] = 'Val parameter "%s=%s" is not supported', ['mt-invalid-scale'] = 'Unit "%s" has invalid scale "%s"', ['mt-both-u-ul'] = 'unit (<b>u</b>) and unit with link (<b>ul</b>) are both specified, only one is allowed.', ['mt-both-up-upl'] = 'unit per (<b>up</b>) and unit per with link (<b>upl</b>) are both specified, only one is allowed.', } local data_module = 'Module:Val/units' local convert_module = 'Module:Convert' local function valerror(msg, nocat, iswarning) -- Return formatted message text for an error or warning. -- Can append "#FormattingError" to URL of a page with a problem to find it. local anchor = '<span id="FormattingError"></span>' local body, category if nocat or mw.title.getCurrentTitle():inNamespaces(1, 2, 3, 5) then -- No category in Talk, User, User_talk, or Wikipedia_talk. category = '' else category = '[[Category:Pages with incorrect formatting templates use]]' end iswarning = false -- problems are infrequent so try showing large error so editor will notice if iswarning then body = '<sup class="noprint Inline-Template" style="white-space:nowrap;">' .. '[[Template:Val|<span title="' .. msg:gsub('"', '&quot;') .. '">warning</span>]]</sup>' else body = '<strong class="error">' .. 'Error in &#123;&#123;[[Template:val|val]]&#125;&#125;: ' .. msg .. '</strong>' end return anchor .. body .. category end local range_types = { -- No need for '&nbsp;' because nowrap applies to all output. [","] = ", ", ["by"] = " by ", ["-"] = "–", ["–"] = "–", ["and"] = " and ", ["or"] = " or " , ["to"] = " to " , ["x"] = " × ", ["×"] = " × ", ["/"] = "/", } local range_repeat_unit = { -- WP:UNIT wants unit repeated when a "multiply" range is used. ["x"] = true, ["×"] = true, } local function extract_item(index, numbers, arg) -- Extract an item from arg and store the result in numbers[index]. -- If no argument or if argument is valid, return nil (no error); -- otherwise, return an error message. -- The stored result is: -- * a table for a number (empty if there was no specified number); or -- * a string for range text -- Input like 1e3 is regarded as invalid for all except argument 1 -- which accepts e notation as an alternative to the 'e' argument. -- Input group separators are removed. local which = index local function fail(msg) local description if which == 'e' then description = mtext['mt-bad-exponent'] else description = mtext['mt-parameter'] .. which end return description .. ' ' .. (msg or mtext['mt-not-number']) .. '.' end local result = {} local range = range_types[arg] if range then if type(index) == 'number' and (index % 2 == 0) then if index == 2 then if numbers[1] and numbers[1].exp then return fail(mtext['mt-cannot-range']) end numbers.has_ranges = true else if not numbers.has_ranges then return fail(mtext['mt-need-range']) end end numbers[index] = range if range_repeat_unit[arg] then -- Any "repeat" range forces unit (if any) to be repeated for all items. numbers.isrepeat = true end return nil end return fail(mtext['mt-not-range']) end if numbers.has_ranges and type(index) == 'number' and (index % 2 == 0) then return fail(mtext['mt-should-range']) end if index == 'e' then local e = numbers[1] and numbers[1].exp if e then if arg then return fail(mtext['mt-cannot-with-e']) end arg = e which = 1 end end if arg and arg ~= '' then arg = arg:gsub(numsep, '') if numdot ~= '.' then arg = arg:gsub(numdot, '.') end if arg:sub(1, 1) == '(' and arg:sub(-1) == ')' then result.parens = true arg = arg:sub(2, -2) end local a, b = arg:match('^(.+)[Ee](.+)$') if a then if index == 1 then arg = a result.exp = b else return fail(mtext['mt-cannot-e']) end end local isnegative, propersign, prefix local minus = '−' prefix, arg = arg:match('^(.-)([%d.]+)$') local value = tonumber(arg) if not value then return fail() end if arg:sub(1, 1) == '.' then arg = '0' .. arg end if prefix == '' then -- Ignore. elseif prefix == '±' then -- Display for first number, ignore for others. if index == 1 then propersign = '±' end elseif prefix == '+' then propersign = '+' elseif prefix == '-' or prefix == minus then propersign = minus isnegative = true else return fail() end result.clean = arg result.sign = propersign or '' result.value = isnegative and -value or value end numbers[index] = result return nil -- no error end local function get_args(numbers, args) -- Extract arguments and store the results in numbers. -- Return nothing (no error) if ok; otherwise, return an error message. for index = 1, 99 do local which = index local arg = args[which] -- has been trimmed if not arg then which = 'e' arg = args[which] end local msg = extract_item(which, numbers, arg) if msg then return msg end if which == 'e' then break end if index > 19 then return mtext['mt-too-many-parameter'] end end if numbers.has_ranges and (#numbers % 2 == 0) then return mtext['mt-need-number'] end end local function get_scale(text, ucode) -- Return the value of text as a number, or throw an error. -- This supports extremely basic expressions of the form: -- a / b -- a ^ b -- where a and b are numbers or 'pi'. local n = tonumber(text) if n then return n end n = text:gsub('pi', math.pi) for _, op in ipairs({ '/', '^' }) do local a, b = n:match('^(.-)' .. op .. '(.*)$') if a then a = tonumber(a) b = tonumber(b) if a and b then if op == '/' then return a / b elseif op == '^' then return a ^ b end end break end end error(string.format(mtext['mt-invalid-scale'], ucode, text)) end local function get_builtin_unit(ucode, definitions) -- Return table of information for the specified built-in unit, or nil if not known. -- Each defined unit code must be followed by two spaces (not tab characters). local _, pos = definitions:find('\n' .. ucode .. ' ', 1, true) if pos then local endline = definitions:find('%s*\n', pos) if endline then local result = {} local n = 0 local text = definitions:sub(pos + 1, endline - 1):gsub('%s%s+', '\t') for item in (text .. '\t'):gmatch('(%S.-)\t') do if item == 'ALIAS' then result.alias = true elseif item == 'ANGLE' then result.isangle = true result.nospace = true elseif item == 'NOSPACE' then result.nospace = true elseif item == 'SI' then result.si = true else n = n + 1 if n == 1 then local link, symbol = item:match('^%[%[([^|]+)|(.+)%]%]$') if link then result.symbol = symbol result.link = link n = 2 else result.symbol = item end elseif n == 2 then result.link = item elseif n == 3 then result.scale_text = item result.scale = get_scale(item, ucode) else result.more_ignored = item break end end end if result.si then local s = result.symbol if ucode == 'mc' .. s or ucode == 'mu' .. s then result.ucode = 'µ' .. s -- unit code for convert should be this end end if n >= 2 or (n >= 1 and result.alias) then return result end -- Ignore invalid definition, treating it as a comment. end end end local function convert_lookup(ucode, value, scaled_top, want_link, si, options) local lookup = require(convert_module)._unit return lookup(ucode, { value = value, scaled_top = scaled_top, link = want_link, si = si, sort = options.sortable, }) end local function get_unit(ucode, value, scaled_top, options) local want_link = options.want_link if scaled_top then want_link = options.want_per_link end local data = mw.loadData(data_module) local result = options.want_longscale and get_builtin_unit(ucode, data.builtin_units_long_scale) or get_builtin_unit(ucode, data.builtin_units) local si, use_convert if result then if result.alias then ucode = result.symbol use_convert = true end if result.scale then -- Setting si means convert will use the unit as given, and the sort key -- will be calculated from the value without any extra scaling that may -- occur if convert found the unit code. For example, if val defines the -- unit 'year' with a scale and if si were not set, convert would also apply -- its own scale because convert knows that a year is 31,557,600 seconds. si = { result.symbol, result.link } value = value * result.scale end if result.si then ucode = result.ucode or ucode si = { result.symbol, result.link } use_convert = true end else result = {} use_convert = true end local convert_unit = convert_lookup(ucode, value, scaled_top, want_link, si, options) result.sortkey = convert_unit.sortspan if use_convert then result.text = convert_unit.text result.scaled_top = convert_unit.scaled_value else if want_link then result.text = '[[' .. result.link .. '|' .. result.symbol .. ']]' else result.text = result.symbol end result.scaled_top = value end return result end local function makeunit(value, options) -- Return table of information for the requested unit and options, or -- return nil if no unit. options = options or {} local unit local ucode = options.u local percode = options.per if ucode then unit = get_unit(ucode, value, nil, options) elseif percode then unit = { nospace = true, scaled_top = value } else return nil end local text = unit.text or '' local sortkey = unit.sortkey if percode then local function bracketed(code, text) return code:find('[*./]') and '(' .. text .. ')' or text end local perunit = get_unit(percode, 1, unit.scaled_top, options) text = (ucode and bracketed(ucode, text) or '') .. '/' .. bracketed(percode, perunit.text) sortkey = perunit.sortkey end if not (unit.nospace or options.nospace) then text = '&nbsp;' .. text end return { text = text, isangle = unit.isangle, sortkey = sortkey } end local function list_units(mode) -- Return wikitext to list the built-in units. -- A unit code should not contain wikimarkup so don't bother escaping. local data = mw.loadData(data_module) local definitions = data.builtin_units .. data.builtin_units_long_scale local last_was_blank = true local n = 0 local result = {} local function add(line) if line == '' then last_was_blank = true else if last_was_blank and n > 0 then n = n + 1 result[n] = '' end last_was_blank = false n = n + 1 result[n] = line end end local si_prefixes = { -- These are the prefixes recognized by convert; u is accepted for micro. y = 'y', z = 'z', a = 'a', f = 'f', p = 'p', n = 'n', u = 'µ', ['µ'] = 'µ', m = 'm', c = 'c', d = 'd', da = 'da', h = 'h', k = 'k', M = 'M', G = 'G', T = 'T', P = 'P', E = 'E', Z = 'Z', Y = 'Y', } local function is_valid(ucode, unit) if unit and not unit.more_ignored then assert(type(unit.symbol) == 'string' and unit.symbol ~= '') if unit.alias then if unit.link or unit.scale_text or unit.si then return false end end if unit.si then if unit.scale_text then return false end ucode = unit.ucode or ucode local base = unit.symbol if ucode == base then unit.display = base return true end local plen = #ucode - #base if plen > 0 then local prefix = si_prefixes[ucode:sub(1, plen)] if prefix and ucode:sub(plen + 1) == base then unit.display = prefix .. base return true end end else unit.display = unit.symbol return true end end return false end local lookup = require(convert_module)._unit local function show_convert(ucode, unit) -- If a built-in unit defines a scale or sets the SI flag, any unit defined in -- convert is not used (the scale or SI prefix's scale is used for a sort key). -- If there is no scale or SI flag, and the unit is not defined in convert, -- the sort key may not be correct; this allows such units to be identified. if not (unit.si or unit.scale_text) then if mode == 'convert' then unit.show = not lookup(unit.alias and unit.symbol or ucode).unknown unit.show_text = 'CONVERT' elseif mode == 'unknown' then unit.show = lookup(unit.alias and unit.symbol or ucode).unknown unit.show_text = 'UNKNOWN' elseif not unit.alias then -- Show convert's scale in square brackets ('[1]' for an unknown unit). -- Don't show scale for an alias because it's misleading for temperature -- and an alias is probably not useful for anything else. local scale = lookup(ucode, {value=1, sort='on'}).scaled_value if type(scale) == 'number' then scale = string.format('%.5g', scale):gsub('e%+?(%-?)0*(%d+)', 'e%1%2') else scale = '?' end unit.show = true unit.show_text = '[' .. scale .. ']' end end end for line in definitions:gmatch('([^\n]*)\n') do local pos, _ = line:find(' ', 1, true) if pos then local ucode = line:sub(1, pos - 1) local unit = get_builtin_unit(ucode, '\n' .. line .. '\n') if is_valid(ucode, unit) then show_convert(ucode, unit) local flags, text if unit.alias then text = unit.symbol else text = '[[' .. unit.link .. '|' .. unit.display .. ']]' end if unit.isangle then unit.nospace = nil -- don't show redundant flag end for _, f in ipairs({ { 'alias', 'ALIAS' }, { 'isangle', 'ANGLE' }, { 'nospace', 'NOSPACE' }, { 'si', 'SI' }, { 'scale_text', unit.scale_text }, { 'show', unit.show_text }, }) do if unit[f[1]] then local t = f[2] if t:match('^%u+$') then t = '<small>' .. t .. '</small>' end if flags then flags = flags .. ' ' .. t else flags = t end end end if flags then text = text .. ' • ' .. flags end add(ucode .. ' = ' .. text .. '<br />') else add(line .. ' ◆ <b>invalid definition</b><br />') end else add(line) end end return table.concat(result, '\n') end local delimit_groups = require('Module:Gapnum').groups local function delimit(sign, numstr, fmt) -- Return sign and numstr (unsigned digits or numdot only) after formatting. -- Four-digit integers are not formatted with gaps. fmt = (fmt or ''):lower() if fmt == 'none' or (fmt == '' and #numstr == 4 and numstr:match('^%d+$')) then return sign .. numstr end -- Group number by integer and decimal parts. -- If there is no decimal part, delimit_groups returns only one table. local ipart, dpart = delimit_groups(numstr) local result if fmt == 'commas' then result = sign .. table.concat(ipart, numsep) if dpart then result = result .. numdot .. table.concat(dpart) end else -- Delimit with a small gap by default. local groups = {} groups[1] = table.remove(ipart, 1) for _, v in ipairs(ipart) do table.insert(groups, '<span style="margin-left:.25em;">' .. v .. '</span>') end if dpart then table.insert(groups, numdot .. (table.remove(dpart, 1) or '')) for _, v in ipairs(dpart) do table.insert(groups, '<span style="margin-left:.25em;">' .. v .. '</span>') end end result = sign .. table.concat(groups) end return result end local function sup_sub(sup, sub, align) -- Return the same result as Module:Su except val defaults to align=right. if align == 'l' or align == 'left' then align = 'left' elseif align == 'c' or align == 'center' then align = 'center' else align = 'right' end return '<span style="display:inline-block;margin-bottom:-0.3em;vertical-align:-0.4em;line-height:1.2em;font-size:85%;text-align:' .. align .. ';">' .. sup .. '<br />' .. sub .. '</span>' end local function range_text(items, unit_table, options) local fmt = options.fmt local nend = items.nend or '' if items.isrepeat or unit_table.isangle then nend = nend .. unit_table.text end local text = '' for i = 1, #items do if i % 2 == 0 then text = text .. items[i] else text = text .. delimit(items[i].sign, items[i].clean, fmt) .. nend end end return text end local function uncertainty_text(uncertainty, unit_table, options) local angle, text, need_parens if unit_table.isangle then angle = unit_table.text end local upper = uncertainty.upper or {} local lower = uncertainty.lower or {} local uncU = upper.clean if uncU then local fmt = options.fmt local uncL = lower.clean if uncL then uncU = delimit('+', uncU, fmt) .. (upper.errend or '') uncL = delimit('−', uncL, fmt) .. (lower.errend or '') if angle then uncU = uncU .. angle uncL = uncL .. angle end text = (angle or '') .. '<span style="margin-left:0.3em;">' .. sup_sub(uncU, uncL, options.align) .. '</span>' else if upper.parens then text = '(' .. uncU .. ')' -- old template did not delimit else text = (angle or '') .. '<span style="margin-left:0.3em;margin-right:0.15em;">±</span>' .. delimit('', uncU, fmt) need_parens = true end if uncertainty.errend then text = text .. uncertainty.errend end if angle then text = text .. angle end end else if angle then text = angle end end return text, need_parens end local function _main(values, unit_spec, options) if options.sandbox then data_module = data_module .. '/sandbox' convert_module = convert_module .. '/sandbox' end local action = options.action if action then if action == 'list' then -- Kludge: am using the align parameter (a=xxx) for type of list. return list_units(options.align) end return valerror('invalid action "' .. action .. '".', options.nocat) end local number = values.number or (values.numbers and values.numbers[1]) or {} local e_10 = options.e or {} local novalue = (number.value == nil and e_10.clean == nil) local fmt = options.fmt local want_sort = true local sortable = options.sortable if sortable == 'off' or (sortable == nil and novalue) then want_sort = false elseif sortable == 'debug' then -- Same as sortable = 'on' but the sort key is displayed. else sortable = 'on' end local sort_value = 1 if want_sort then sort_value = number.value or 1 if e_10.value and sort_value ~= 0 then -- The 'if' avoids {{val|0|e=1234}} giving an invalid sort_value due to overflow. sort_value = sort_value * 10^e_10.value end end local unit_table = makeunit(sort_value, { u = unit_spec.u, want_link = unit_spec.want_link, per = unit_spec.per, want_per_link = unit_spec.want_per_link, nospace = novalue, want_longscale = unit_spec.want_longscale, sortable = sortable, }) local sortkey if unit_table then if want_sort then sortkey = unit_table.sortkey end else unit_table = { text = '' } if want_sort then sortkey = convert_lookup('dummy', sort_value, nil, nil, nil, { sortable = sortable }).sortspan end end local final_unit = unit_table.isangle and '' or unit_table.text local e_text, n_text, need_parens local uncertainty = values.uncertainty if uncertainty then if number.clean then n_text = delimit(number.sign, number.clean, fmt) .. (number.nend or '') local text text, need_parens = uncertainty_text(uncertainty, unit_table, options) if text then n_text = n_text .. text end else n_text = '' end else if values.numbers.isrepeat then final_unit = '' end n_text = range_text(values.numbers, unit_table, options) need_parens = true end if e_10.clean then if need_parens then n_text = '(' .. n_text .. ')' end e_text = '10<sup>' .. delimit(e_10.sign, e_10.clean, fmt) .. '</sup>' if number.clean then e_text = '<span style="margin-left:0.25em;margin-right:0.15em;">×</span>' .. e_text end else e_text = '' end local result = (sortkey or '') .. (options.prefix or '') .. n_text .. e_text .. final_unit .. (options.suffix or '') if result ~= '' then result = '<span class="nowrap">' .. result .. '</span>' end return result .. (options.warning or '') end local function check_parameters(args, has_ranges, nocat) -- Return warning text for the first problem parameter found, or nothing if ok. local whitelist = { a = true, action = true, debug = true, e = true, ['end'] = true, errend = true, ['+errend'] = true, ['-errend'] = true, fmt = true, ['long scale'] = true, long_scale = true, longscale = true, nocategory = true, p = true, s = true, sortable = true, u = true, ul = true, up = true, upl = true, } for k, v in pairs(args) do if type(k) == 'string' and not whitelist[k] then local warning = string.format(mtext['mt-val-not-supported'], k, v) return valerror(warning, nocat, true) end end if not has_ranges and args[4] then return valerror(mtext['mt-ignore-parameter4'], nocat, true) end end local function main(frame) local getArgs = require('Module:Arguments').getArgs local args = getArgs(frame, {wrappers = { 'Template:Val' }}) local nocat = args.nocategory local numbers = {} -- table of number tables, perhaps with range text local msg = get_args(numbers, args) if msg then return valerror(msg, nocat) end if args.u and args.ul then return valerror(mtext['mt-both-u-ul'], nocat) end if args.up and args.upl then return valerror(mtext['mt-both-up-upl'], nocat) end local values if numbers.has_ranges then -- Multiple values with range separators but no uncertainty. numbers.nend = args['end'] values = { numbers = numbers, } else -- A single value with optional uncertainty. local function setfield(i, dst, src) local v = args[src] if v then if numbers[i] then numbers[i][dst] = v else numbers[i] = { [dst] = v } end end end setfield(1, 'nend', 'end') setfield(2, 'errend', '+errend') setfield(3, 'errend', '-errend') values = { number = numbers[1], uncertainty = { upper = numbers[2], lower = numbers[3], errend = args.errend, } } end local unit_spec = { u = args.ul or args.u, want_link = args.ul ~= nil, per = args.upl or args.up, want_per_link = args.upl ~= nil, want_longscale = (args.longscale or args.long_scale or args['long scale']) == 'on', } local options = { action = args.action, align = args.a, e = numbers.e, fmt = args.fmt, nocat = nocat, prefix = args.p, sandbox = string.find(frame:getTitle(), 'sandbox', 1, true) ~= nil, sortable = args.sortable or (args.debug == 'yes' and 'debug' or nil), suffix = args.s, warning = check_parameters(args, numbers.has_ranges, nocat), } return _main(values, unit_spec, options) end return { main = main, _main = _main } 899cf01cf6a449e10309108c9de56689e4205d5c Module:Gapnum 828 44 104 103 2022-09-04T15:24:29Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local p = {} local getArgs function p.main(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end local args = getArgs(frame, {wrappers = 'Template:Gapnum'}) local n = args[1] if not n then error('Parameter 1 is required') elseif not tonumber(n) and not tonumber(n, 36) then -- Validates any number with base ≤ 36 error('Unable to convert "' .. args[1] .. '" to a number') end local gap = args.gap local precision = tonumber(args.prec) return p.gaps(n,{gap=gap,prec=precision}) end -- Not named p._main so that it has a better function name when required by Module:Val function p.gaps(n,tbl) local nstr = tostring(n) if not tbl then tbl = {} end local gap = tbl.gap or '.25em' local int_part, frac_part = p.groups(n,tbl.prec) local ret = mw.html.create('span') :css('white-space','nowrap') -- No gap necessary on first group :wikitext(table.remove(int_part,1)) -- Build int part for _, v in ipairs(int_part) do ret:tag('span') :css('margin-left',gap) :wikitext(v) end if frac_part then -- The first group after the decimal shouldn't have a gap ret:wikitext('.' .. table.remove(frac_part,1)) -- Build frac part for _, v in ipairs(frac_part) do ret:tag('span') :css('margin-left',gap) :wikitext(v) end end return ret end -- Creates tables where each element is a different group of the number function p.groups(num,precision) local nstr = tostring(num) if not precision then precision = -1 end local decimalloc = nstr:find('.', 1, true) local int_part, frac_part if decimalloc == nil then int_part = nstr else int_part = nstr:sub(1, decimalloc-1) frac_part = nstr:sub(decimalloc + 1) end -- only define ret_i as an empty table, let ret_d stay nil local ret_i,ret_d = {} -- Loop to handle most of the groupings; from right to left, so that if a group has less than 3 members, it will be the first group while int_part:len() > 3 do -- Insert in first spot, since we're moving backwards table.insert(ret_i,1,int_part:sub(-3)) int_part = int_part:sub(1,-4) end -- handle any left over numbers if int_part:len() > 0 then table.insert(ret_i,1,int_part) end if precision ~= 0 and frac_part then ret_d = {} if precision == -1 then precision = frac_part:len() end -- Reduce the length of the string if required precision is less than actual precision -- OR -- Increase it (by adding 0s) if the required precision is more than actual local offset = precision - frac_part:len() if offset < 0 then frac_part = frac_part:sub(1,precision) elseif offset > 0 then frac_part = frac_part .. string.rep('0', offset) end -- Allow groups of 3 or 2 (3 first) for v in string.gmatch(frac_part,'%d%d%d?') do table.insert(ret_d,v) end -- Preference for groups of 4 instead of groups of 1 at the end if #frac_part % 3 == 1 then if frac_part:len() == 1 then ret_d = {frac_part} else local last_g = ret_d[#ret_d] or '' last_g = last_g..frac_part:sub(-1) ret_d[#ret_d] = last_g end end end return ret_i,ret_d end return p b855346e2e3abc47591f883503c6108f922f0849 Module:Convert 828 46 108 107 2022-09-04T15:24:31Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- Convert a value from one unit of measurement to another. -- Example: {{convert|123|lb|kg}} --> 123 pounds (56 kg) -- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki. local MINUS = '−' -- Unicode U+2212 MINUS SIGN (UTF-8: e2 88 92) local abs = math.abs local floor = math.floor local format = string.format local log10 = math.log10 local ustring = mw.ustring local ulen = ustring.len local usub = ustring.sub -- Configuration options to keep magic values in one location. -- Conversion data and message text are defined in separate modules. local config, maxsigfig local numdot -- must be '.' or ',' or a character which works in a regex local numsep, numsep_remove, numsep_remove2 local data_code, all_units local text_code local varname -- can be a code to use variable names that depend on value local from_en_table -- to translate an output string of en digits to local language local to_en_table -- to translate an input string of digits in local language to en -- Use translation_table in convert/text to change the following. local en_default -- true uses lang=en unless convert has lang=local or local digits local group_method = 3 -- code for how many digits are in a group local per_word = 'per' -- for units like "liters per kilometer" local plural_suffix = 's' -- only other useful value is probably '' to disable plural unit names local omitsep -- true to omit separator before local symbol/name -- All units should be defined in the data module. However, to cater for quick changes -- and experiments, any unknown unit is looked up in an extra data module, if it exists. -- That module would be transcluded in only a small number of pages, so there should be -- little server overhead from making changes, and changes should propagate quickly. local extra_module -- name of module with extra units local extra_units -- nil or table of extra units from extra_module -- Some options in the invoking template can set variables used later in the module. local currency_text -- for a user-defined currency symbol: {{convert|12|$/ha|$=€}} (euro replaces dollar) local function from_en(text) -- Input is a string representing a number in en digits with '.' decimal mark, -- without digit grouping (which is done just after calling this). -- Return the translation of the string with numdot and digits in local language. if numdot ~= '.' then text = text:gsub('%.', numdot) end if from_en_table then text = text:gsub('%d', from_en_table) end return text end local function to_en(text) -- Input is a string representing a number in the local language with -- an optional numdot decimal mark and numsep digit grouping. -- Return the translation of the string with '.' mark and en digits, -- and no separators (they have to be removed here to handle cases like -- numsep = '.' and numdot = ',' with input "1.234.567,8"). if to_en_table then text = ustring.gsub(text, '%d', to_en_table) end if numsep_remove then text = text:gsub(numsep_remove, '') end if numsep_remove2 then text = text:gsub(numsep_remove2, '') end if numdot ~= '.' then text = text:gsub(numdot, '.') end return text end local function decimal_mark(text) -- Return ',' if text probably is using comma for decimal mark, or has no decimal mark. -- Return '.' if text probably is using dot for decimal mark. -- Otherwise return nothing (decimal mark not known). if not text:find('[.,]') then return ',' end text = text:gsub('^%-', ''):gsub('%+%d+/%d+$', ''):gsub('[Ee]%-?%d+$', '') local decimal = text:match('^0?([.,])%d+$') or text:match('%d([.,])%d?%d?$') or text:match('%d([.,])%d%d%d%d+$') if decimal then return decimal end if text:match('%.%d+%.') then return ',' end if text:match('%,%d+,') then return '.' end end local add_warning, with_separator -- forward declarations local function to_en_with_check(text, parms) -- Version of to_en() for a wiki using numdot = ',' and numsep = '.' to check -- text (an input number as a string) which might have been copied from enwiki. -- For example, in '1.234' the '.' could be a decimal mark or a group separator. -- From viwiki. if to_en_table then text = ustring.gsub(text, '%d', to_en_table) end if decimal_mark(text) == '.' then local original = text text = text:gsub(',', '') -- for example, interpret "1,234.5" as an enwiki value if parms then add_warning(parms, 0, 'cvt_enwiki_num', original, with_separator({}, text)) end else if numsep_remove then text = text:gsub(numsep_remove, '') end if numsep_remove2 then text = text:gsub(numsep_remove2, '') end if numdot ~= '.' then text = text:gsub(numdot, '.') end end return text end local function omit_separator(id) -- Return true if there should be no separator before id (a unit symbol or name). -- For zhwiki, there should be no separator if id uses local characters. -- The following kludge should be a sufficient test. if omitsep then if id:sub(1, 2) == '-{' then -- for "-{...}-" content language variant return true end if id:byte() > 127 then local first = usub(id, 1, 1) if first ~= 'Å' and first ~= '°' and first ~= 'µ' then return true end end end return id:sub(1, 1) == '/' -- no separator before units like "/ha" end local spell_module -- name of module that can spell numbers local speller -- function from that module to handle spelling (set if needed) local wikidata_module, wikidata_data_module -- names of Wikidata modules local wikidata_code, wikidata_data -- exported tables from those modules (set if needed) local function set_config(args) -- Set configuration options from template #invoke or defaults. config = args maxsigfig = config.maxsigfig or 14 -- maximum number of significant figures local data_module, text_module local sandbox = config.sandbox and ('/' .. config.sandbox) or '' data_module = "Module:Convert/data" .. sandbox text_module = "Module:Convert/text" .. sandbox extra_module = "Module:Convert/extra" .. sandbox wikidata_module = "Module:Convert/wikidata" .. sandbox wikidata_data_module = "Module:Convert/wikidata/data" .. sandbox spell_module = "Module:ConvertNumeric" data_code = mw.loadData(data_module) text_code = mw.loadData(text_module) all_units = data_code.all_units local translation = text_code.translation_table if translation then numdot = translation.numdot numsep = translation.numsep if numdot == ',' and numsep == '.' then if text_code.all_messages.cvt_enwiki_num then to_en = to_en_with_check end end if translation.group then group_method = translation.group end if translation.per_word then per_word = translation.per_word end if translation.plural_suffix then plural_suffix = translation.plural_suffix end varname = translation.varname from_en_table = translation.from_en local use_workaround = true if use_workaround then -- 2013-07-05 workaround bug by making a copy of the required table. -- mw.ustring.gsub fails with a table (to_en_table) as the replacement, -- if the table is accessed via mw.loadData. local source = translation.to_en if source then to_en_table = {} for k, v in pairs(source) do to_en_table[k] = v end end else to_en_table = translation.to_en end if translation.lang == 'en default' then en_default = true -- for hiwiki end omitsep = translation.omitsep -- for zhwiki end numdot = config.numdot or numdot or '.' -- decimal mark before fractional digits numsep = config.numsep or numsep or ',' -- group separator for numbers -- numsep should be ',' or '.' or '' or '&nbsp;' or a Unicode character. -- numsep_remove must work in a regex to identify separators to be removed. if numsep ~= '' then numsep_remove = (numsep == '.') and '%.' or numsep end if numsep ~= ',' and numdot ~= ',' then numsep_remove2 = ',' -- so numbers copied from enwiki will work end end local function collection() -- Return a table to hold items. return { n = 0, add = function (self, item) self.n = self.n + 1 self[self.n] = item end, } end local function divide(numerator, denominator) -- Return integers quotient, remainder resulting from dividing the two -- given numbers, which should be unsigned integers. local quotient, remainder = floor(numerator / denominator), numerator % denominator if not (0 <= remainder and remainder < denominator) then -- Floating point limits may need this, as in {{convert|160.02|Ym|ydftin}}. remainder = 0 end return quotient, remainder end local function split(text, delimiter) -- Return a numbered table with fields from splitting text. -- The delimiter is used in a regex without escaping (for example, '.' would fail). -- Each field has any leading/trailing whitespace removed. local t = {} text = text .. delimiter -- to get last item for item in text:gmatch('%s*(.-)%s*' .. delimiter) do table.insert(t, item) end return t end local function strip(text) -- If text is a string, return its content with no leading/trailing -- whitespace. Otherwise return nil (a nil argument gives a nil result). if type(text) == 'string' then return text:match("^%s*(.-)%s*$") end end local function table_len(t) -- Return length (<100) of a numbered table to replace #t which is -- documented to not work if t is accessed via mw.loadData(). for i = 1, 100 do if t[i] == nil then return i - 1 end end end local function wanted_category(catkey, catsort, want_warning) -- Return message category if it is wanted in current namespace, -- otherwise return ''. local cat local title = mw.title.getCurrentTitle() if title then local nsdefault = '0' -- default namespace: '0' = article; '0,10' = article and template local namespace = title.namespace for _, v in ipairs(split(config.nscat or nsdefault, ',')) do if namespace == tonumber(v) then cat = text_code.all_categories[want_warning and 'warning' or catkey] if catsort and catsort ~= '' and cat:sub(-2) == ']]' then cat = cat:sub(1, -3) .. '|' .. mw.text.nowiki(usub(catsort, 1, 20)) .. ']]' end break end end end return cat or '' end local function message(parms, mcode, is_warning) -- Return wikitext for an error message, including category if specified -- for the message type. -- mcode = numbered table specifying the message: -- mcode[1] = 'cvt_xxx' (string used as a key to get message info) -- mcode[2] = 'parm1' (string to replace '$1' if any in message) -- mcode[3] = 'parm2' (string to replace '$2' if any in message) -- mcode[4] = 'parm3' (string to replace '$3' if any in message) local msg if type(mcode) == 'table' then if mcode[1] == 'cvt_no_output' then -- Some errors should cause convert to output an empty string, -- for example, for an optional field in an infobox. return '' end msg = text_code.all_messages[mcode[1]] end parms.have_problem = true local function subparm(fmt, ...) local rep = {} for i, v in ipairs({...}) do rep['$' .. i] = v end return (fmt:gsub('$%d+', rep)) end if msg then local parts = {} local regex, replace = msg.regex, msg.replace for i = 1, 3 do local limit = 40 local s = mcode[i + 1] if s then if regex and replace then s = s:gsub(regex, replace) limit = nil -- allow long "should be" messages end -- Escape user input so it does not break the message. -- To avoid tags (like {{convert|1<math>23</math>|m}}) breaking -- the mouseover title, any strip marker starting with char(127) is -- replaced with '...' (text not needing i18n). local append local pos = s:find(string.char(127), 1, true) if pos then append = '...' s = s:sub(1, pos - 1) end if limit and ulen(s) > limit then s = usub(s, 1, limit) append = '...' end s = mw.text.nowiki(s) .. (append or '') else s = '?' end parts['$' .. i] = s end local function ispreview() -- Return true if a prominent message should be shown. if parms.test == 'preview' or parms.test == 'nopreview' then -- For testing, can preview a real message or simulate a preview -- when running automated tests. return parms.test == 'preview' end local success, revid = pcall(function () return (parms.frame):preprocess('{{REVISIONID}}') end) return success and (revid == '') end local want_warning = is_warning and not config.warnings and -- show unobtrusive warnings if config.warnings not configured not msg.nowarn -- but use msg settings, not standard warning, if specified local title = string.gsub(msg[1] or 'Missing message', '$%d+', parts) local text = want_warning and '*' or msg[2] or 'Missing message' local cat = wanted_category(msg[3], mcode[2], want_warning) local anchor = msg[4] or '' local fmtkey = ispreview() and 'cvt_format_preview' or (want_warning and 'cvt_format2' or msg.format or 'cvt_format') local fmt = text_code.all_messages[fmtkey] or 'convert: bug' return subparm(fmt, title:gsub('"', '&quot;'), text, cat, anchor) end return 'Convert internal error: unknown message' end function add_warning(parms, level, key, text1, text2) -- for forward declaration above -- If enabled, add a warning that will be displayed after the convert result. -- A higher level is more verbose: more kinds of warnings are displayed. -- To reduce output noise, only the first warning is displayed. if level <= (tonumber(config.warnings) or 1) then if parms.warnings == nil then parms.warnings = message(parms, { key, text1, text2 }, true) end end end local function spell_number(parms, inout, number, numerator, denominator) -- Return result of spelling (number, numerator, denominator), or -- return nil if spelling is not available or not supported for given text. -- Examples (each value must be a string or nil): -- number numerator denominator output -- ------ --------- ----------- ------------------- -- "1.23" nil nil one point two three -- "1" "2" "3" one and two thirds -- nil "2" "3" two thirds if not speller then local function get_speller(module) return require(module).spell_number end local success success, speller = pcall(get_speller, spell_module) if not success or type(speller) ~= 'function' then add_warning(parms, 1, 'cvt_no_spell', 'spell') return nil end end local case if parms.spell_upper == inout then case = true parms.spell_upper = nil -- only uppercase first word in a multiple unit end local sp = not parms.opt_sp_us local adj = parms.opt_adjectival return speller(number, numerator, denominator, case, sp, adj) end ------------------------------------------------------------------------ -- BEGIN: Code required only for built-in units. -- LATER: If need much more code, move to another module to simplify this module. local function speed_of_sound(altitude) -- This is for the Mach built-in unit of speed. -- Return speed of sound in metres per second at given altitude in feet. -- If no altitude given, use default (zero altitude = sea level). -- Table gives speed of sound in miles per hour at various altitudes: -- altitude = -17,499 to 402,499 feet -- mach_table[a + 4] = s where -- a = (altitude / 5000) rounded to nearest integer (-3 to 80) -- s = speed of sound (mph) at that altitude -- LATER: Should calculate result from an interpolation between the next -- lower and higher altitudes in table, rather than rounding to nearest. -- From: http://www.aerospaceweb.org/question/atmosphere/q0112.shtml local mach_table = { -- a = 799.5, 787.0, 774.2, 761.207051, -- -3 to 0 748.0, 734.6, 721.0, 707.0, 692.8, 678.3, 663.5, 660.1, 660.1, 660.1, -- 1 to 10 660.1, 660.1, 660.1, 662.0, 664.3, 666.5, 668.9, 671.1, 673.4, 675.6, -- 11 to 20 677.9, 683.7, 689.9, 696.0, 702.1, 708.1, 714.0, 719.9, 725.8, 731.6, -- 21 to 30 737.3, 737.7, 737.7, 736.2, 730.5, 724.6, 718.8, 712.9, 707.0, 701.0, -- 31 to 40 695.0, 688.9, 682.8, 676.6, 670.4, 664.1, 657.8, 652.9, 648.3, 643.7, -- 41 to 50 639.1, 634.4, 629.6, 624.8, 620.0, 615.2, 613.2, 613.2, 613.2, 613.5, -- 51 to 60 614.4, 615.3, 616.7, 619.8, 623.4, 629.7, 635.0, 641.1, 650.6, 660.0, -- 61 to 70 672.5, 674.3, 676.1, 677.9, 679.7, 681.5, 683.3, 685.1, 686.8, 688.6, -- 71 to 80 } altitude = altitude or 0 local a = (altitude < 0) and -altitude or altitude a = floor(a / 5000 + 0.5) if altitude < 0 then a = -a end if a < -3 then a = -3 elseif a > 80 then a = 80 end return mach_table[a + 4] * 0.44704 -- mph converted to m/s end -- END: Code required only for built-in units. ------------------------------------------------------------------------ local function add_style(parms, class) -- Add selected template style to parms if not already present. parms.templatestyles = parms.templatestyles or {} if not parms.templatestyles[class] then parms.templatestyles[class] = parms.frame:extensionTag({ name = 'templatestyles', args = { src = text_code.titles[class] } }) end end local function get_styles(parms) -- Return string of required template styles, empty if none. if parms.templatestyles then local t = {} for _, v in pairs(parms.templatestyles) do table.insert(t, v) end return table.concat(t) end return '' end local function get_range(word) -- Return a range (string or table) corresponding to word (like "to"), -- or return nil if not a range word. local ranges = text_code.ranges return ranges.types[word] or ranges.types[ranges.aliases[word]] end local function check_mismatch(unit1, unit2) -- If unit1 cannot be converted to unit2, return an error message table. -- This allows conversion between units of the same type, and between -- Nm (normally torque) and ftlb (energy), as in gun-related articles. -- This works because Nm is the base unit (scale = 1) for both the -- primary type (torque), and the alternate type (energy, where Nm = J). -- A match occurs if the primary types are the same, or if unit1 matches -- the alternate type of unit2, and vice versa. That provides a whitelist -- of which conversions are permitted between normally incompatible types. if unit1.utype == unit2.utype or (unit1.utype == unit2.alttype and unit1.alttype == unit2.utype) then return nil end return { 'cvt_mismatch', unit1.utype, unit2.utype } end local function override_from(out_table, in_table, fields) -- Copy the specified fields from in_table to out_table, but do not -- copy nil fields (keep any corresponding field in out_table). for _, field in ipairs(fields) do if in_table[field] then out_table[field] = in_table[field] end end end local function shallow_copy(t) -- Return a shallow copy of table t. -- Do not need the features and overhead of the Scribunto mw.clone(). local result = {} for k, v in pairs(t) do result[k] = v end return result end local unit_mt = { -- Metatable to get missing values for a unit that does not accept SI prefixes. -- Warning: The boolean value 'false' is returned for any missing field -- so __index is not called twice for the same field in a given unit. __index = function (self, key) local value if key == 'name1' or key == 'sym_us' then value = self.symbol elseif key == 'name2' then value = self.name1 .. plural_suffix elseif key == 'name1_us' then value = self.name1 if not rawget(self, 'name2_us') then -- If name1_us is 'foot', do not make name2_us by appending plural_suffix. self.name2_us = self.name2 end elseif key == 'name2_us' then local raw1_us = rawget(self, 'name1_us') if raw1_us then value = raw1_us .. plural_suffix else value = self.name2 end elseif key == 'link' then value = self.name1 else value = false end rawset(self, key, value) return value end } local function prefixed_name(unit, name, index) -- Return unit name with SI prefix inserted at correct position. -- index = 1 (name1), 2 (name2), 3 (name1_us), 4 (name2_us). -- The position is a byte (not character) index, so use Lua's sub(). local pos = rawget(unit, 'prefix_position') if type(pos) == 'string' then pos = tonumber(split(pos, ',')[index]) end if pos then return name:sub(1, pos - 1) .. unit.si_name .. name:sub(pos) end return unit.si_name .. name end local unit_prefixed_mt = { -- Metatable to get missing values for a unit that accepts SI prefixes. -- Before use, fields si_name, si_prefix must be defined. -- The unit must define _symbol, _name1 and -- may define _sym_us, _name1_us, _name2_us -- (_sym_us, _name2_us may be defined for a language using sp=us -- to refer to a variant unrelated to U.S. units). __index = function (self, key) local value if key == 'symbol' then value = self.si_prefix .. self._symbol elseif key == 'sym_us' then value = rawget(self, '_sym_us') if value then value = self.si_prefix .. value else value = self.symbol end elseif key == 'name1' then value = prefixed_name(self, self._name1, 1) elseif key == 'name2' then value = rawget(self, '_name2') if value then value = prefixed_name(self, value, 2) else value = self.name1 .. plural_suffix end elseif key == 'name1_us' then value = rawget(self, '_name1_us') if value then value = prefixed_name(self, value, 3) else value = self.name1 end elseif key == 'name2_us' then value = rawget(self, '_name2_us') if value then value = prefixed_name(self, value, 4) elseif rawget(self, '_name1_us') then value = self.name1_us .. plural_suffix else value = self.name2 end elseif key == 'link' then value = self.name1 else value = false end rawset(self, key, value) return value end } local unit_per_mt = { -- Metatable to get values for a per unit of form "x/y". -- This is never called to determine a unit name or link because per units -- are handled as a special case. -- Similarly, the default output is handled elsewhere, and for a symbol -- this is only called from get_default() for default_exceptions. __index = function (self, key) local value if key == 'symbol' then local per = self.per local unit1, unit2 = per[1], per[2] if unit1 then value = unit1[key] .. '/' .. unit2[key] else value = '/' .. unit2[key] end elseif key == 'sym_us' then value = self.symbol elseif key == 'scale' then local per = self.per local unit1, unit2 = per[1], per[2] value = (unit1 and unit1.scale or 1) * self.scalemultiplier / unit2.scale else value = false end rawset(self, key, value) return value end } local function make_per(unitcode, unit_table, ulookup) -- Return true, t where t is a per unit with unit codes expanded to unit tables, -- or return false, t where t is an error message table. local result = { unitcode = unitcode, utype = unit_table.utype, per = {} } override_from(result, unit_table, { 'invert', 'iscomplex', 'default', 'link', 'symbol', 'symlink' }) result.symbol_raw = (result.symbol or false) -- to distinguish between a defined exception and a metatable calculation local prefix for i, v in ipairs(unit_table.per) do if i == 1 and v == '' then -- First unit symbol can be empty; that gives a nil first unit table. elseif i == 1 and text_code.currency[v] then prefix = currency_text or v else local success, t = ulookup(v) if not success then return false, t end result.per[i] = t end end local multiplier = unit_table.multiplier if not result.utype then -- Creating an automatic per unit. local unit1 = result.per[1] local utype = (unit1 and unit1.utype or prefix or '') .. '/' .. result.per[2].utype local t = data_code.per_unit_fixups[utype] if t then if type(t) == 'table' then utype = t.utype or utype result.link = result.link or t.link multiplier = multiplier or t.multiplier else utype = t end end result.utype = utype end result.scalemultiplier = multiplier or 1 result.vprefix = prefix or false -- set to non-nil to avoid calling __index return true, setmetatable(result, unit_per_mt) end local function lookup(parms, unitcode, what, utable, fails, depth) -- Return true, t where t is a copy of the unit's converter table, -- or return false, t where t is an error message table. -- Parameter 'what' determines whether combination units are accepted: -- 'no_combination' : single unit only -- 'any_combination' : single unit or combination or output multiple -- 'only_multiple' : single unit or output multiple only -- Parameter unitcode is a symbol (like 'g'), with an optional SI prefix (like 'kg'). -- If, for example, 'kg' is in this table, that entry is used; -- otherwise the prefix ('k') is applied to the base unit ('g'). -- If unitcode is a known combination code (and if allowed by what), -- a table of output multiple unit tables is included in the result. -- For compatibility with the old template, an underscore in a unitcode is -- replaced with a space so usage like {{convert|350|board_feet}} works. -- Wikignomes may also put two spaces or "&nbsp;" in combinations, so -- replace underscore, "&nbsp;", and multiple spaces with a single space. utable = utable or parms.unittable or all_units fails = fails or {} depth = depth and depth + 1 or 1 if depth > 9 then -- There are ways to mistakenly define units which result in infinite -- recursion when lookup() is called. That gives a long delay and very -- confusing error messages, so the depth parameter is used as a guard. return false, { 'cvt_lookup', unitcode } end if unitcode == nil or unitcode == '' then return false, { 'cvt_no_unit' } end unitcode = unitcode:gsub('_', ' '):gsub('&nbsp;', ' '):gsub(' +', ' ') local function call_make_per(t) return make_per(unitcode, t, function (ucode) return lookup(parms, ucode, 'no_combination', utable, fails, depth) end ) end local t = utable[unitcode] if t then if t.shouldbe then return false, { 'cvt_should_be', t.shouldbe } end if t.sp_us then parms.opt_sp_us = true end local target = t.target -- nil, or unitcode is an alias for this target if target then local success, result = lookup(parms, target, what, utable, fails, depth) if not success then return false, result end override_from(result, t, { 'customary', 'default', 'link', 'symbol', 'symlink' }) local multiplier = t.multiplier if multiplier then result.multiplier = tostring(multiplier) result.scale = result.scale * multiplier end return true, result end if t.per then return call_make_per(t) end local combo = t.combination -- nil or a table of unitcodes if combo then local multiple = t.multiple if what == 'no_combination' or (what == 'only_multiple' and not multiple) then return false, { 'cvt_bad_unit', unitcode } end -- Recursively create a combination table containing the -- converter table of each unitcode. local result = { utype = t.utype, multiple = multiple, combination = {} } local cvt = result.combination for i, v in ipairs(combo) do local success, t = lookup(parms, v, multiple and 'no_combination' or 'only_multiple', utable, fails, depth) if not success then return false, t end cvt[i] = t end return true, result end local result = shallow_copy(t) result.unitcode = unitcode if result.prefixes then result.si_name = '' result.si_prefix = '' return true, setmetatable(result, unit_prefixed_mt) end return true, setmetatable(result, unit_mt) end local SIprefixes = text_code.SIprefixes for plen = SIprefixes[1] or 2, 1, -1 do -- Look for an SI prefix; should never occur with an alias. -- Check for longer prefix first ('dam' is decametre). -- SIprefixes[1] = prefix maximum #characters (as seen by mw.ustring.sub). local prefix = usub(unitcode, 1, plen) local si = SIprefixes[prefix] if si then local t = utable[usub(unitcode, plen+1)] if t and t.prefixes then local result = shallow_copy(t) result.unitcode = unitcode result.si_name = parms.opt_sp_us and si.name_us or si.name result.si_prefix = si.prefix or prefix result.scale = t.scale * 10 ^ (si.exponent * t.prefixes) return true, setmetatable(result, unit_prefixed_mt) end end end -- Accept user-defined combinations like "acre+m2+ha" or "acre m2 ha" for output. -- If '+' is used, each unit code can include a space, and any error is fatal. -- If ' ' is used and if each space-separated word is a unit code, it is a combo, -- but errors are not fatal so the unit code can be looked up as an extra unit. local err_is_fatal local combo = collection() if unitcode:find('+', 1, true) then err_is_fatal = true for item in (unitcode .. '+'):gmatch('%s*(.-)%s*%+') do if item ~= '' then combo:add(item) end end elseif unitcode:find('%s') then for item in unitcode:gmatch('%S+') do combo:add(item) end end if combo.n > 1 then local function lookup_combo() if what == 'no_combination' or what == 'only_multiple' then return false, { 'cvt_bad_unit', unitcode } end local result = { combination = {} } local cvt = result.combination for i, v in ipairs(combo) do local success, t = lookup(parms, v, 'only_multiple', utable, fails, depth) if not success then return false, t end if i == 1 then result.utype = t.utype else local mismatch = check_mismatch(result, t) if mismatch then return false, mismatch end end cvt[i] = t end return true, result end local success, result = lookup_combo() if success or err_is_fatal then return success, result end end -- Accept any unit with an engineering notation prefix like "e6cuft" -- (million cubic feet), but not chained prefixes like "e3e6cuft", -- and not if the unit is a combination or multiple, -- and not if the unit has an offset or is a built-in. -- Only en digits are accepted. local exponent, baseunit = unitcode:match('^e(%d+)(.*)') if exponent then local engscale = text_code.eng_scales[exponent] if engscale then local success, result = lookup(parms, baseunit, 'no_combination', utable, fails, depth) if success and not (result.offset or result.builtin or result.engscale) then result.unitcode = unitcode -- 'e6cuft' not 'cuft' result.defkey = unitcode -- key to lookup default exception result.engscale = engscale result.scale = result.scale * 10 ^ tonumber(exponent) return true, result end end end -- Look for x/y; split on right-most slash to get scale correct (x/y/z is x/y per z). local top, bottom = unitcode:match('^(.-)/([^/]+)$') if top and not unitcode:find('e%d') then -- If valid, create an automatic per unit for an "x/y" unit code. -- The unitcode must not include extraneous spaces. -- Engineering notation (apart from at start and which has been stripped before here), -- is not supported so do not make a per unit if find text like 'e3' in unitcode. local success, result = call_make_per({ per = {top, bottom} }) if success then return true, result end end if not parms.opt_ignore_error and not get_range(unitcode) then -- Want the "what links here" list for the extra_module to show only cases -- where an extra unit is used, so do not require it if invoked from {{val}} -- or if looking up a range word which cannot be a unit. if not extra_units then local success, extra = pcall(function () return require(extra_module).extra_units end) if success and type(extra) == 'table' then extra_units = extra end end if extra_units then -- A unit in one data table might refer to a unit in the other table, so -- switch between them, relying on fails or depth to terminate loops. if not fails[unitcode] then fails[unitcode] = true local other = (utable == all_units) and extra_units or all_units local success, result = lookup(parms, unitcode, what, other, fails, depth) if success then return true, result end end end end if to_en_table then -- At fawiki it is common to translate all digits so a unit like "km2" becomes "km۲". local en_code = ustring.gsub(unitcode, '%d', to_en_table) if en_code ~= unitcode then return lookup(parms, en_code, what, utable, fails, depth) end end return false, { 'cvt_unknown', unitcode } end local function valid_number(num) -- Return true if num is a valid number. -- In Scribunto (different from some standard Lua), when expressed as a string, -- overflow or other problems are indicated with text like "inf" or "nan" -- which are regarded as invalid here (each contains "n"). if type(num) == 'number' and tostring(num):find('n', 1, true) == nil then return true end end local function hyphenated(name, parts) -- Return a hyphenated form of given name (for adjectival usage). -- The name may be linked and the target of the link must not be changed. -- Hypothetical examples: -- [[long ton|ton]] → [[long ton|ton]] (no change) -- [[tonne|long ton]] → [[tonne|long-ton]] -- [[metric ton|long ton]] → [[metric ton|long-ton]] -- [[long ton]] → [[long ton|long-ton]] -- Input can also have multiple links in a single name like: -- [[United States customary units|U.S.]] [[US gallon|gallon]] -- [[mile]]s per [[United States customary units|U.S.]] [[quart]] -- [[long ton]]s per [[short ton]] -- Assume that links cannot be nested (never like "[[abc[[def]]ghi]]"). -- This uses a simple and efficient procedure that works for most cases. -- Some units (if used) would require more, and can later think about -- adding a method to handle exceptions. -- The procedure is to replace each space with a hyphen, but -- not a space after ')' [for "(pre-1954&nbsp;US) nautical mile"], and -- not spaces immediately before '(' or in '(...)' [for cases like -- "British thermal unit (ISO)" and "Calorie (International Steam Table)"]. if name:find(' ', 1, true) then if parts then local pos if name:sub(1, 1) == '(' then pos = name:find(')', 1, true) if pos then return name:sub(1, pos+1) .. name:sub(pos+2):gsub(' ', '-') end elseif name:sub(-1) == ')' then pos = name:find('(', 1, true) if pos then return name:sub(1, pos-2):gsub(' ', '-') .. name:sub(pos-1) end end return name:gsub(' ', '-') end parts = collection() for before, item, after in name:gmatch('([^[]*)(%[%[[^[]*%]%])([^[]*)') do if item:find(' ', 1, true) then local prefix local plen = item:find('|', 1, true) if plen then prefix = item:sub(1, plen) item = item:sub(plen + 1, -3) else prefix = item:sub(1, -3) .. '|' item = item:sub(3, -3) end item = prefix .. hyphenated(item, parts) .. ']]' end parts:add(before:gsub(' ', '-') .. item .. after:gsub(' ', '-')) end if parts.n == 0 then -- No link like "[[...]]" was found in the original name. parts:add(hyphenated(name, parts)) end return table.concat(parts) end return name end local function hyphenated_maybe(parms, want_name, sep, id, inout) -- Return s, f where -- s = id, possibly modified -- f = true if hyphenated -- Possible modifications: hyphenate; prepend '-'; append mid text. if id == nil or id == '' then return '' end local mid = (inout == (parms.opt_flip and 'out' or 'in')) and parms.mid or '' if want_name then if parms.opt_adjectival then return '-' .. hyphenated(id) .. mid, true end if parms.opt_add_s and id:sub(-1) ~= 's' then id = id .. 's' -- for nowiki end end return sep .. id .. mid end local function use_minus(text) -- Return text with Unicode minus instead of '-', if present. if text:sub(1, 1) == '-' then return MINUS .. text:sub(2) end return text end local function digit_groups(parms, text, method) -- Return a numbered table of groups of digits (left-to-right, in local language). -- Parameter method is a number or nil: -- 3 for 3-digit grouping (default), or -- 2 for 3-then-2 grouping (only for digits before decimal mark). local len_right local len_left = text:find('.', 1, true) if len_left then len_right = #text - len_left len_left = len_left - 1 else len_left = #text end local twos = method == 2 and len_left > 5 local groups = collection() local run = len_left local n if run < 4 or (run == 4 and parms.opt_comma5) then if parms.opt_gaps then n = run else n = #text end elseif twos then n = run % 2 == 0 and 1 or 2 else n = run % 3 == 0 and 3 or run % 3 end while run > 0 do groups:add(n) run = run - n n = (twos and run > 3) and 2 or 3 end if len_right then if groups.n == 0 then groups:add(0) end if parms.opt_gaps and len_right > 3 then local want4 = not parms.opt_gaps3 -- true gives no gap before trailing single digit local isfirst = true run = len_right while run > 0 do n = (want4 and run == 4) and 4 or (run > 3 and 3 or run) if isfirst then isfirst = false groups[groups.n] = groups[groups.n] + 1 + n else groups:add(n) end run = run - n end else groups[groups.n] = groups[groups.n] + 1 + len_right end end local pos = 1 for i, length in ipairs(groups) do groups[i] = from_en(text:sub(pos, pos + length - 1)) pos = pos + length end return groups end function with_separator(parms, text) -- for forward declaration above -- Input text is a number in en digits with optional '.' decimal mark. -- Return an equivalent, formatted for display: -- with a custom decimal mark instead of '.', if wanted -- with thousand separators inserted, if wanted -- digits in local language -- The given text is like '123' or '123.' or '12345.6789'. -- The text has no sign (caller inserts that later, if necessary). -- When using gaps, they are inserted before and after the decimal mark. -- Separators are inserted only before the decimal mark. -- A trailing dot (as in '123.') is removed because their use appears to -- be accidental, and such a number should be shown as '123' or '123.0'. -- It is useful for convert to suppress the dot so, for example, '4000.' -- is a simple way of indicating that all the digits are significant. if text:sub(-1) == '.' then text = text:sub(1, -2) end if #text < 4 or parms.opt_nocomma or numsep == '' then return from_en(text) end local groups = digit_groups(parms, text, group_method) if parms.opt_gaps then if groups.n <= 1 then return groups[1] or '' end local nowrap = '<span style="white-space: nowrap">' local gap = '<span style="margin-left: 0.25em">' local close = '</span>' return nowrap .. groups[1] .. gap .. table.concat(groups, close .. gap, 2, groups.n) .. close .. close end return table.concat(groups, numsep) end -- An input value like 1.23e12 is displayed using scientific notation (1.23×10¹²). -- That also makes the output use scientific notation, except for small values. -- In addition, very small or very large output values use scientific notation. -- Use format(fmtpower, significand, '10', exponent) where each argument is a string. local fmtpower = '%s<span style="margin:0 .15em 0 .25em">×</span>%s<sup>%s</sup>' local function with_exponent(parms, show, exponent) -- Return wikitext to display the implied value in scientific notation. -- Input uses en digits; output uses digits in local language. return format(fmtpower, with_separator(parms, show), from_en('10'), use_minus(from_en(tostring(exponent)))) end local function make_sigfig(value, sigfig) -- Return show, exponent that are equivalent to the result of -- converting the number 'value' (where value >= 0) to a string, -- rounded to 'sigfig' significant figures. -- The returned items are: -- show: a string of digits; no sign and no dot; -- there is an implied dot before show. -- exponent: a number (an integer) to shift the implied dot. -- Resulting value = tonumber('.' .. show) * 10^exponent. -- Examples: -- make_sigfig(23.456, 3) returns '235', 2 (.235 * 10^2). -- make_sigfig(0.0023456, 3) returns '235', -2 (.235 * 10^-2). -- make_sigfig(0, 3) returns '000', 1 (.000 * 10^1). if sigfig <= 0 then sigfig = 1 elseif sigfig > maxsigfig then sigfig = maxsigfig end if value == 0 then return string.rep('0', sigfig), 1 end local exp, fracpart = math.modf(log10(value)) if fracpart >= 0 then fracpart = fracpart - 1 exp = exp + 1 end local digits = format('%.0f', 10^(fracpart + sigfig)) if #digits > sigfig then -- Overflow (for sigfig=3: like 0.9999 rounding to "1000"; need "100"). digits = digits:sub(1, sigfig) exp = exp + 1 end assert(#digits == sigfig, 'Bug: rounded number has wrong length') return digits, exp end -- Fraction output format. local fracfmt = { { -- Like {{frac}} (fraction slash). '<span class="frac" role="math">{SIGN}<span class="num">{NUM}</span>&frasl;<span class="den">{DEN}</span></span>', -- 1/2 '<span class="frac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="num">{NUM}</span>&frasl;<span class="den">{DEN}</span></span>', -- 1+2/3 style = 'frac', }, { -- Like {{sfrac}} (stacked fraction, that is, horizontal bar). '<span class="sfrac tion" role="math">{SIGN}<span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span>', -- 1//2 '<span class="sfrac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="tion"><span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span></span>', -- 1+2//3 style = 'sfrac', }, } local function format_fraction(parms, inout, negative, wholestr, numstr, denstr, do_spell, style) -- Return wikitext for a fraction, possibly spelled. -- Inputs use en digits and have no sign; output uses digits in local language. local wikitext if not style then style = parms.opt_fraction_horizontal and 2 or 1 end if wholestr == '' then wholestr = nil end local substitute = { SIGN = negative and MINUS or '', WHOLE = wholestr and with_separator(parms, wholestr), NUM = from_en(numstr), DEN = from_en(denstr), } wikitext = fracfmt[style][wholestr and 2 or 1]:gsub('{(%u+)}', substitute) if do_spell then if negative then if wholestr then wholestr = '-' .. wholestr else numstr = '-' .. numstr end end local s = spell_number(parms, inout, wholestr, numstr, denstr) if s then return s end end add_style(parms, fracfmt[style].style) return wikitext end local function format_number(parms, show, exponent, isnegative) -- Parameter show is a string or a table containing strings. -- Each string is a formatted number in en digits and optional '.' decimal mark. -- A table represents a fraction: integer, numerator, denominator; -- if a table is given, exponent must be nil. -- Return t where t is a table with fields: -- show = wikitext formatted to display implied value -- (digits in local language) -- is_scientific = true if show uses scientific notation -- clean = unformatted show (possibly adjusted and with inserted '.') -- (en digits) -- sign = '' or MINUS -- exponent = exponent (possibly adjusted) -- The clean and exponent fields can be used to calculate the -- rounded absolute value, if needed. -- -- The value implied by the arguments is found from: -- exponent is nil; and -- show is a string of digits (no sign), with an optional dot; -- show = '123.4' is value 123.4, '1234' is value 1234.0; -- or: -- exponent is an integer indicating where dot should be; -- show is a string of digits (no sign and no dot); -- there is an implied dot before show; -- show does not start with '0'; -- show = '1234', exponent = 3 is value 0.1234*10^3 = 123.4. -- -- The formatted result: -- * Is for an output value and is spelled if wanted and possible. -- * Includes a Unicode minus if isnegative and not spelled. -- * Uses a custom decimal mark, if wanted. -- * Has digits grouped where necessary, if wanted. -- * Uses scientific notation if requested, or for very small or large values -- (which forces result to not be spelled). -- * Has no more than maxsigfig significant digits -- (same as old template and {{#expr}}). local xhi, xlo -- these control when scientific notation (exponent) is used if parms.opt_scientific then xhi, xlo = 4, 2 -- default for output if input uses e-notation elseif parms.opt_scientific_always then xhi, xlo = 0, 0 -- always use scientific notation (experimental) else xhi, xlo = 10, 4 -- default end local sign = isnegative and MINUS or '' local maxlen = maxsigfig local tfrac if type(show) == 'table' then tfrac = show show = tfrac.wholestr assert(exponent == nil, 'Bug: exponent given with fraction') end if not tfrac and not exponent then local integer, dot, decimals = show:match('^(%d*)(%.?)(.*)') if integer == '0' or integer == '' then local zeros, figs = decimals:match('^(0*)([^0]?.*)') if #figs == 0 then if #zeros > maxlen then show = '0.' .. zeros:sub(1, maxlen) end elseif #zeros >= xlo then show = figs exponent = -#zeros elseif #figs > maxlen then show = '0.' .. zeros .. figs:sub(1, maxlen) end elseif #integer >= xhi then show = integer .. decimals exponent = #integer else maxlen = maxlen + #dot if #show > maxlen then show = show:sub(1, maxlen) end end end if exponent then local function zeros(n) return string.rep('0', n) end if #show > maxlen then show = show:sub(1, maxlen) end if exponent > xhi or exponent <= -xlo or (exponent == xhi and show ~= '1' .. zeros(xhi - 1)) then -- When xhi, xlo = 10, 4 (the default), scientific notation is used if the -- rounded value satisfies: value >= 1e9 or value < 1e-4 (1e9 = 0.1e10), -- except if show is '1000000000' (1e9), for example: -- {{convert|1000000000|m|m|sigfig=10}} → 1,000,000,000 metres (1,000,000,000 m) local significand if #show > 1 then significand = show:sub(1, 1) .. '.' .. show:sub(2) else significand = show end return { clean = '.' .. show, exponent = exponent, sign = sign, show = sign .. with_exponent(parms, significand, exponent-1), is_scientific = true, } end if exponent >= #show then show = show .. zeros(exponent - #show) -- result has no dot elseif exponent <= 0 then show = '0.' .. zeros(-exponent) .. show else show = show:sub(1, exponent) .. '.' .. show:sub(exponent+1) end end local formatted_show if tfrac then show = tostring(tfrac.value) -- to set clean in returned table formatted_show = format_fraction(parms, 'out', isnegative, tfrac.wholestr, tfrac.numstr, tfrac.denstr, parms.opt_spell_out) else if isnegative and show:match('^0.?0*$') then sign = '' -- don't show minus if result is negative but rounds to zero end formatted_show = sign .. with_separator(parms, show) if parms.opt_spell_out then formatted_show = spell_number(parms, 'out', sign .. show) or formatted_show end end return { clean = show, sign = sign, show = formatted_show, is_scientific = false, -- to avoid calling __index } end local function extract_fraction(parms, text, negative) -- If text represents a fraction, return -- value, altvalue, show, denominator -- where -- value is a number (value of the fraction in argument text) -- altvalue is an alternate interpretation of any fraction for the hands -- unit where "12.1+3/4" means 12 hands 1.75 inches -- show is a string (formatted text for display of an input value, -- and is spelled if wanted and possible) -- denominator is value of the denominator in the fraction -- Otherwise, return nil. -- Input uses en digits and '.' decimal mark (input has been translated). -- Output uses digits in local language and local decimal mark, if any. ------------------------------------------------------------------------ -- Originally this function accepted x+y/z where x, y, z were any valid -- numbers, possibly with a sign. For example '1.23e+2+1.2/2.4' = 123.5, -- and '2-3/8' = 1.625. However, such usages were found to be errors or -- misunderstandings, so since August 2014 the following restrictions apply: -- x (if present) is an integer or has a single digit after decimal mark -- y and z are unsigned integers -- e-notation is not accepted -- The overall number can start with '+' or '-' (so '12+3/4' and '+12+3/4' -- and '-12-3/4' are valid). -- Any leading negative sign is removed by the caller, so only inputs -- like the following are accepted here (may have whitespace): -- negative = false false true (there was a leading '-') -- text = '2/3' '+2/3' '2/3' -- text = '1+2/3' '+1+2/3' '1-2/3' -- text = '12.3+1/2' '+12.3+1/2' '12.3-1/2' -- Values like '12.3+1/2' are accepted, but are intended only for use -- with the hands unit (not worth adding code to enforce that). ------------------------------------------------------------------------ local leading_plus, prefix, numstr, slashes, denstr = text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*(/+)%s*(%d+)%s*$') if not leading_plus then -- Accept a single U+2044 fraction slash because that may be pasted. leading_plus, prefix, numstr, denstr = text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*⁄%s*(%d+)%s*$') slashes = '/' end local numerator = tonumber(numstr) local denominator = tonumber(denstr) if numerator == nil or denominator == nil or (negative and leading_plus ~= '') then return nil end local whole, wholestr if prefix == '' then wholestr = '' whole = 0 else -- Any prefix must be like '12+' or '12-' (whole number and fraction sign); -- '12.3+' and '12.3-' are also accepted (single digit after decimal point) -- because '12.3+1/2 hands' is valid (12 hands 3½ inches). local num1, num2, frac_sign = prefix:match('^(%d+)(%.?%d?)%s*([+%-])$') if num1 == nil then return nil end if num2 == '' then -- num2 must be '' or like '.1' but not '.' or '.12' wholestr = num1 else if #num2 ~= 2 then return nil end wholestr = num1 .. num2 end if frac_sign ~= (negative and '-' or '+') then return nil end whole = tonumber(wholestr) if whole == nil then return nil end end local value = whole + numerator / denominator if not valid_number(value) then return nil end local altvalue = whole + numerator / (denominator * 10) local style = #slashes -- kludge: 1 or 2 slashes can be used to select style if style > 2 then style = 2 end local wikitext = format_fraction(parms, 'in', negative, leading_plus .. wholestr, numstr, denstr, parms.opt_spell_in, style) return value, altvalue, wikitext, denominator end local function extract_number(parms, text, another, no_fraction) -- Return true, info if can extract a number from text, -- where info is a table with the result, -- or return false, t where t is an error message table. -- Input can use en digits or digits in local language and can -- have references at the end. Accepting references is intended -- for use in infoboxes with a field for a value passed to convert. -- Parameter another = true if the expected value is not the first. -- Before processing, the input text is cleaned: -- * Any thousand separators (valid or not) are removed. -- * Any sign is replaced with '-' (if negative) or '' (otherwise). -- That replaces Unicode minus with '-'. -- If successful, the returned info table contains named fields: -- value = a valid number -- altvalue = a valid number, usually same as value but different -- if fraction used (for hands unit) -- singular = true if value is 1 or -1 (to use singular form of units) -- clean = cleaned text with any separators and sign removed -- (en digits and '.' decimal mark) -- show = text formatted for output, possibly with ref strip markers -- (digits in local language and custom decimal mark) -- The resulting show: -- * Is for an input value and is spelled if wanted and possible. -- * Has a rounded value, if wanted. -- * Has digits grouped where necessary, if wanted. -- * If negative, a Unicode minus is used; otherwise the sign is -- '+' (if the input text used '+'), or is '' (if no sign in input). text = strip(text or '') local reference local pos = text:find('\127', 1, true) if pos then local before = text:sub(1, pos - 1) local remainder = text:sub(pos) local refs = {} while #remainder > 0 do local ref, spaces ref, spaces, remainder = remainder:match('^(\127[^\127]*UNIQ[^\127]*%-ref[^\127]*\127)(%s*)(.*)') if ref then table.insert(refs, ref) else refs = {} break end end if #refs > 0 then text = strip(before) reference = table.concat(refs) end end local clean = to_en(text, parms) if clean == '' then return false, { another and 'cvt_no_num2' or 'cvt_no_num' } end local isnegative, propersign = false, '' -- most common case local singular, show, denominator local value = tonumber(clean) local altvalue if value then local sign = clean:sub(1, 1) if sign == '+' or sign == '-' then propersign = (sign == '+') and '+' or MINUS clean = clean:sub(2) end if value < 0 then isnegative = true value = -value end else local valstr for _, prefix in ipairs({ '-', MINUS, '&minus;' }) do -- Including '-' sets isnegative in case input is a fraction like '-2-3/4'. local plen = #prefix if clean:sub(1, plen) == prefix then valstr = clean:sub(plen + 1) if valstr:match('^%s') then -- "- 1" is invalid but "-1 - 1/2" is ok return false, { 'cvt_bad_num', text } end break end end if valstr then isnegative = true propersign = MINUS clean = valstr value = tonumber(clean) end if value == nil then if not no_fraction then value, altvalue, show, denominator = extract_fraction(parms, clean, isnegative) end if value == nil then return false, { 'cvt_bad_num', text } end if value <= 1 then singular = true -- for example, "½ mile" or "one half mile" (singular unit) end end end if not valid_number(value) then -- for example, "1e310" may overflow return false, { 'cvt_invalid_num' } end if show == nil then -- clean is a non-empty string with no spaces, and does not represent a fraction, -- and value = tonumber(clean) is a number >= 0. -- If the input uses e-notation, show will be displayed using a power of ten, but -- we use the number as given so it might not be normalized scientific notation. -- The input value is spelled if specified so any e-notation is ignored; -- that allows input like 2e6 to be spelled as "two million" which works -- because the spell module converts '2e6' to '2000000' before spelling. local function rounded(value, default, exponent) local precision = parms.opt_ri if precision then local fmt = '%.' .. format('%d', precision) .. 'f' local result = fmt:format(tonumber(value) + 2e-14) -- fudge for some common cases of bad rounding if not exponent then singular = (tonumber(result) == 1) end return result end return default end singular = (value == 1) local scientific local significand, exponent = clean:match('^([%d.]+)[Ee]([+%-]?%d+)') if significand then show = with_exponent(parms, rounded(significand, significand, exponent), exponent) scientific = true else show = with_separator(parms, rounded(value, clean)) end show = propersign .. show if parms.opt_spell_in then show = spell_number(parms, 'in', propersign .. rounded(value, clean)) or show scientific = false end if scientific then parms.opt_scientific = true end end if isnegative and (value ~= 0) then value = -value altvalue = -(altvalue or value) end return true, { value = value, altvalue = altvalue or value, singular = singular, clean = clean, show = show .. (reference or ''), denominator = denominator, } end local function get_number(text) -- Return v, f where: -- v = nil (text is not a number) -- or -- v = value of text (text is a number) -- f = true if value is an integer -- Input can use en digits or digits in local language or separators, -- but no Unicode minus, and no fraction. if text then local number = tonumber(to_en(text)) if number then local _, fracpart = math.modf(number) return number, (fracpart == 0) end end end local function gcd(a, b) -- Return the greatest common denominator for the given values, -- which are known to be positive integers. if a > b then a, b = b, a end if a <= 0 then return b end local r = b % a if r <= 0 then return a end if r == 1 then return 1 end return gcd(r, a) end local function fraction_table(value, denominator) -- Return value as a string or a table: -- * If result is a string, there is no fraction, and the result -- is value formatted as a string of en digits. -- * If result is a table, it represents a fraction with named fields: -- wholestr, numstr, denstr (strings of en digits for integer, numerator, denominator). -- The result is rounded to the nearest multiple of (1/denominator). -- If the multiple is zero, no fraction is included. -- No fraction is included if value is very large as the fraction would -- be unhelpful, particularly if scientific notation is required. -- Input value is a non-negative number. -- Input denominator is a positive integer for the desired fraction. if value <= 0 then return '0' end if denominator <= 0 or value > 1e8 then return format('%.2f', value) end local integer, decimals = math.modf(value) local numerator = floor((decimals * denominator) + 0.5 + 2e-14) -- add fudge for some common cases of bad rounding if numerator >= denominator then integer = integer + 1 numerator = 0 end local wholestr = tostring(integer) if numerator > 0 then local div = gcd(numerator, denominator) if div > 1 then numerator = numerator / div denominator = denominator / div end return { wholestr = (integer > 0) and wholestr or '', numstr = tostring(numerator), denstr = tostring(denominator), value = value, } end return wholestr end local function preunits(count, preunit1, preunit2) -- If count is 1: -- ignore preunit2 -- return p1 -- else: -- preunit1 is used for preunit2 if the latter is empty -- return p1, p2 -- where: -- p1 is text to insert before the input unit -- p2 is text to insert before the output unit -- p1 or p2 may be nil to mean "no preunit" -- Using '+' gives output like "5+ feet" (no space before, but space after). local function withspace(text, wantboth) -- Return text with space before and, if wantboth, after. -- However, no space is added if there is a space or '&nbsp;' or '-' -- at that position ('-' is for adjectival text). -- There is also no space if text starts with '&' -- (e.g. '&deg;' would display a degree symbol with no preceding space). local char = text:sub(1, 1) if char == '&' then return text -- an html entity can be used to specify the exact display end if not (char == ' ' or char == '-' or char == '+') then text = ' ' .. text end if wantboth then char = text:sub(-1, -1) if not (char == ' ' or char == '-' or text:sub(-6, -1) == '&nbsp;') then text = text .. ' ' end end return text end local PLUS = '+ ' preunit1 = preunit1 or '' local trim1 = strip(preunit1) if count == 1 then if trim1 == '' then return nil end if trim1 == '+' then return PLUS end return withspace(preunit1, true) end preunit1 = withspace(preunit1) preunit2 = preunit2 or '' local trim2 = strip(preunit2) if trim1 == '+' then if trim2 == '' or trim2 == '+' then return PLUS, PLUS end preunit1 = PLUS end if trim2 == '' then if trim1 == '' then return nil, nil end preunit2 = preunit1 elseif trim2 == '+' then preunit2 = PLUS elseif trim2 == '&#32;' then -- trick to make preunit2 empty preunit2 = nil else preunit2 = withspace(preunit2) end return preunit1, preunit2 end local function range_text(range, want_name, parms, before, after, inout, options) -- Return before .. rtext .. after -- where rtext is the text that separates two values in a range. local rtext, adj_text, exception options = options or {} if type(range) == 'table' then -- Table must specify range text for ('off' and 'on') or ('input' and 'output'), -- and may specify range text for 'adj=on', -- and may specify exception = true. rtext = range[want_name and 'off' or 'on'] or range[((inout == 'in') == (parms.opt_flip == true)) and 'output' or 'input'] adj_text = range['adj'] exception = range['exception'] else rtext = range end if parms.opt_adjectival then if want_name or (exception and parms.abbr_org == 'on') then rtext = adj_text or rtext:gsub(' ', '-'):gsub('&nbsp;', '-') end end if rtext == '–' and (options.spaced or after:sub(1, #MINUS) == MINUS) then rtext = '&nbsp;– ' end return before .. rtext .. after end local function get_composite(parms, iparm, in_unit_table) -- Look for a composite input unit. For example, {{convert|1|yd|2|ft|3|in}} -- would result in a call to this function with -- iparm = 3 (parms[iparm] = "2", just after the first unit) -- in_unit_table = (unit table for "yd"; contains value 1 for number of yards) -- Return true, iparm, unit where -- iparm = index just after the composite units (7 in above example) -- unit = composite unit table holding all input units, -- or return true if no composite unit is present in parms, -- or return false, t where t is an error message table. local default, subinfo local composite_units, count = { in_unit_table }, 1 local fixups = {} local total = in_unit_table.valinfo[1].value local subunit = in_unit_table while subunit.subdivs do -- subdivs is nil or a table of allowed subdivisions local subcode = strip(parms[iparm+1]) local subdiv = subunit.subdivs[subcode] or subunit.subdivs[(all_units[subcode] or {}).target] if not subdiv then break end local success success, subunit = lookup(parms, subcode, 'no_combination') if not success then return false, subunit end -- should never occur success, subinfo = extract_number(parms, parms[iparm]) if not success then return false, subinfo end iparm = iparm + 2 subunit.inout = 'in' subunit.valinfo = { subinfo } -- Recalculate total as a number of subdivisions. -- subdiv[1] = number of subdivisions per previous unit (integer > 1). total = total * subdiv[1] + subinfo.value if not default then -- set by the first subdiv with a default defined default = subdiv.default end count = count + 1 composite_units[count] = subunit if subdiv.unit or subdiv.name then fixups[count] = { unit = subdiv.unit, name = subdiv.name, valinfo = subunit.valinfo } end end if count == 1 then return true -- no error and no composite unit end for i, fixup in pairs(fixups) do local unit = fixup.unit local name = fixup.name if not unit or (count > 2 and name) then composite_units[i].fixed_name = name else local success, alternate = lookup(parms, unit, 'no_combination') if not success then return false, alternate end -- should never occur alternate.inout = 'in' alternate.valinfo = fixup.valinfo composite_units[i] = alternate end end return true, iparm, { utype = in_unit_table.utype, scale = subunit.scale, -- scale of last (least significant) unit valinfo = { { value = total, clean = subinfo.clean, denominator = subinfo.denominator } }, composite = composite_units, default = default or in_unit_table.default } end local function translate_parms(parms, kv_pairs) -- Update fields in parms by translating each key:value in kv_pairs to terms -- used by this module (may involve translating from local language to English). -- Also, checks are performed which may display warnings, if enabled. -- Return true if successful or return false, t where t is an error message table. currency_text = nil -- local testing can hold module in memory; must clear globals if kv_pairs.adj and kv_pairs.sing then -- For enwiki (before translation), warn if attempt to use adj and sing -- as the latter is a deprecated alias for the former. if kv_pairs.adj ~= kv_pairs.sing and kv_pairs.sing ~= '' then add_warning(parms, 1, 'cvt_unknown_option', 'sing=' .. kv_pairs.sing) end kv_pairs.sing = nil end kv_pairs.comma = kv_pairs.comma or config.comma -- for plwiki who want default comma=5 for loc_name, loc_value in pairs(kv_pairs) do local en_name = text_code.en_option_name[loc_name] if en_name then local en_value = text_code.en_option_value[en_name] if en_value == 'INTEGER' then -- altitude_ft, altitude_m, frac, sigfig en_value = nil if loc_value == '' then add_warning(parms, 2, 'cvt_empty_option', loc_name) else local minimum local number, is_integer = get_number(loc_value) if en_name == 'sigfig' then minimum = 1 elseif en_name == 'frac' then minimum = 2 if number and number < 0 then parms.opt_fraction_horizontal = true number = -number end else minimum = -1e6 end if number and is_integer and number >= minimum then en_value = number else local m if en_name == 'frac' then m = 'cvt_bad_frac' elseif en_name == 'sigfig' then m = 'cvt_bad_sigfig' else m = 'cvt_bad_altitude' end add_warning(parms, 1, m, loc_name .. '=' .. loc_value) end end elseif en_value == 'TEXT' then -- $, input, qid, qual, stylein, styleout, tracking en_value = loc_value ~= '' and loc_value or nil -- accept non-empty user text with no validation if not en_value and (en_name == '$' or en_name == 'qid' or en_name == 'qual') then add_warning(parms, 2, 'cvt_empty_option', loc_name) elseif en_name == '$' then -- Value should be a single character like "€" for the euro currency symbol, but anything is accepted. currency_text = (loc_value == 'euro') and '€' or loc_value elseif en_name == 'input' then -- May have something like {{convert|input=}} (empty input) if source is an infobox -- with optional fields. In that case, want to output nothing rather than an error. parms.input_text = loc_value -- keep input because parms.input is nil if loc_value == '' end else en_value = en_value[loc_value] if en_value and en_value:sub(-1) == '?' then en_value = en_value:sub(1, -2) add_warning(parms, -1, 'cvt_deprecated', loc_name .. '=' .. loc_value) end if en_value == nil then if loc_value == '' then add_warning(parms, 2, 'cvt_empty_option', loc_name) else add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value) end elseif en_value == '' then en_value = nil -- an ignored option like adj=off elseif type(en_value) == 'string' and en_value:sub(1, 4) == 'opt_' then for _, v in ipairs(split(en_value, ',')) do local lhs, rhs = v:match('^(.-)=(.+)$') if rhs then parms[lhs] = tonumber(rhs) or rhs else parms[v] = true end end en_value = nil end end parms[en_name] = en_value else add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value) end end local abbr_entered = parms.abbr local cfg_abbr = config.abbr if cfg_abbr then -- Don't warn if invalid because every convert would show that warning. if cfg_abbr == 'on always' then parms.abbr = 'on' elseif cfg_abbr == 'off always' then parms.abbr = 'off' elseif parms.abbr == nil then if cfg_abbr == 'on default' then parms.abbr = 'on' elseif cfg_abbr == 'off default' then parms.abbr = 'off' end end end if parms.abbr then if parms.abbr == 'unit' then parms.abbr = 'on' parms.number_word = true end parms.abbr_org = parms.abbr -- original abbr, before any flip elseif parms.opt_hand_hh then parms.abbr_org = 'on' parms.abbr = 'on' else parms.abbr = 'out' -- default is to abbreviate output only (use symbol, not name) end if parms.opt_order_out then -- Disable options that do not work in a useful way with order=out. parms.opt_flip = nil -- override adj=flip parms.opt_spell_in = nil parms.opt_spell_out = nil parms.opt_spell_upper = nil end if parms.opt_spell_out and not abbr_entered then parms.abbr = 'off' -- should show unit name when spelling the output value end if parms.opt_flip then local function swap_in_out(option) local value = parms[option] if value == 'in' then parms[option] = 'out' elseif value == 'out' then parms[option] = 'in' end end swap_in_out('abbr') swap_in_out('lk') if parms.opt_spell_in and not parms.opt_spell_out then -- For simplicity, and because it does not appear to be needed, -- user cannot set an option to spell the output only. parms.opt_spell_in = nil parms.opt_spell_out = true end end if parms.opt_spell_upper then parms.spell_upper = parms.opt_flip and 'out' or 'in' end if parms.opt_table or parms.opt_tablecen then if abbr_entered == nil and parms.lk == nil then parms.opt_values = true end parms.table_align = parms.opt_table and 'right' or 'center' end if parms.table_align or parms.opt_sortable_on then parms.need_table_or_sort = true end local disp_joins = text_code.disp_joins local default_joins = disp_joins['b'] parms.join_between = default_joins[3] or '; ' local disp = parms.disp if disp == nil then -- special case for the most common setting parms.joins = default_joins elseif disp == 'x' then -- Later, parms.joins is set from the input parameters. else -- Old template does this. local abbr = parms.abbr if disp == 'slash' then if abbr_entered == nil then disp = 'slash-nbsp' elseif abbr == 'in' or abbr == 'out' then disp = 'slash-sp' else disp = 'slash-nosp' end elseif disp == 'sqbr' then if abbr == 'on' then disp = 'sqbr-nbsp' else disp = 'sqbr-sp' end end parms.joins = disp_joins[disp] or default_joins parms.join_between = parms.joins[3] or parms.join_between parms.wantname = parms.joins.wantname end if (en_default and not parms.opt_lang_local and (parms[1] or ''):find('%d')) or parms.opt_lang_en then from_en_table = nil end if en_default and from_en_table then -- For hiwiki: localized symbol/name is defined with the US symbol/name field, -- and is used if output uses localized numbers. parms.opt_sp_us = true end return true end local function get_values(parms) -- If successful, update parms and return true, v, i where -- v = table of input values -- i = index to next entry in parms after those processed here -- or return false, t where t is an error message table. local valinfo = collection() -- numbered table of input values local range = collection() -- numbered table of range items (having, for example, 2 range items requires 3 input values) local had_nocomma -- true if removed "nocomma" kludge from second parameter (like "tonocomma") local parm2 = strip(parms[2]) if parm2 and parm2:sub(-7, -1) == 'nocomma' then parms[2] = strip(parm2:sub(1, -8)) parms.opt_nocomma = true had_nocomma = true end local function extractor(i) -- If the parameter is not a value, try unpacking it as a range ("1-23" for "1 to 23"). -- However, "-1-2/3" is a negative fraction (-1⅔), so it must be extracted first. -- Do not unpack a parameter if it is like "3-1/2" which is sometimes incorrectly -- used instead of "3+1/2" (and which should not be interpreted as "3 to ½"). -- Unpacked items are inserted into the parms table. -- The tail recursion allows combinations like "1x2 to 3x4". local valstr = strip(parms[i]) -- trim so any '-' as a negative sign will be at start local success, result = extract_number(parms, valstr, i > 1) if not success and valstr and i < 20 then -- check i to limit abuse local lhs, sep, rhs = valstr:match('^(%S+)%s+(%S+)%s+(%S.*)') if lhs and not (sep == '-' and rhs:match('/')) then if sep:find('%d') then return success, result -- to reject {{convert|1 234 567|m}} with a decent message (en only) end parms[i] = rhs table.insert(parms, i, sep) table.insert(parms, i, lhs) return extractor(i) end if not valstr:match('%-.*/') then for _, sep in ipairs(text_code.ranges.words) do local start, stop = valstr:find(sep, 2, true) -- start at 2 to skip any negative sign for range '-' if start then parms[i] = valstr:sub(stop + 1) table.insert(parms, i, sep) table.insert(parms, i, valstr:sub(1, start - 1)) return extractor(i) end end end end return success, result end local i = 1 local is_change while true do local success, info = extractor(i) -- need to set parms.opt_nocomma before calling this if not success then return false, info end i = i + 1 if is_change then info.is_change = true -- value is after "±" and so is a change (significant for range like {{convert|5|±|5|°C}}) is_change = nil end valinfo:add(info) local range_item = get_range(strip(parms[i])) if not range_item then break end i = i + 1 range:add(range_item) if type(range_item) == 'table' then -- For range "x", if append unit to some values, append it to all. parms.in_range_x = parms.in_range_x or range_item.in_range_x parms.out_range_x = parms.out_range_x or range_item.out_range_x parms.abbr_range_x = parms.abbr_range_x or range_item.abbr_range_x is_change = range_item.is_range_change end end if range.n > 0 then if range.n > 30 then -- limit abuse, although 4 is a more likely upper limit return false, { 'cvt_invalid_num' } -- misleading message but it will do end parms.range = range elseif had_nocomma then return false, { 'cvt_unknown', parm2 } end return true, valinfo, i end local function simple_get_values(parms) -- If input is like "{{convert|valid_value|valid_unit|...}}", -- return true, i, in_unit, in_unit_table -- i = index in parms of what follows valid_unit, if anything. -- The valid_value is not negative and does not use a fraction, and -- no options requiring further processing of the input are used. -- Otherwise, return nothing or return false, parm1 for caller to interpret. -- Testing shows this function is successful for 96% of converts in articles, -- and that on average it speeds up converts by 8%. local clean = to_en(strip(parms[1] or ''), parms) if parms.opt_ri or parms.opt_spell_in or #clean > 10 or not clean:match('^[0-9.]+$') then return false, clean end local value = tonumber(clean) if not value then return end local info = { value = value, altvalue = value, singular = (value == 1), clean = clean, show = with_separator(parms, clean), } local in_unit = strip(parms[2]) local success, in_unit_table = lookup(parms, in_unit, 'no_combination') if not success then return end in_unit_table.valinfo = { info } return true, 3, in_unit, in_unit_table end local function wikidata_call(parms, operation, ...) -- Return true, s where s is the result of a Wikidata operation, -- or return false, t where t is an error message table. local function worker(...) wikidata_code = wikidata_code or require(wikidata_module) wikidata_data = wikidata_data or mw.loadData(wikidata_data_module) return wikidata_code[operation](wikidata_data, ...) end local success, status, result = pcall(worker, ...) if success then return status, result end if parms.opt_sortable_debug then -- Use debug=yes to crash if an error while accessing Wikidata. error('Error accessing Wikidata: ' .. status, 0) end return false, { 'cvt_wd_fail' } end local function get_parms(parms, args) -- If successful, update parms and return true, unit where -- parms is a table of all arguments passed to the template -- converted to named arguments, and -- unit is the input unit table; -- or return false, t where t is an error message table. -- For special processing (not a convert), can also return -- true, wikitext where wikitext is the final result. -- The returned input unit table may be for a fake unit using the specified -- unit code as the symbol and name, and with bad_mcode = message code table. -- MediaWiki removes leading and trailing whitespace from the values of -- named arguments. However, the values of numbered arguments include any -- whitespace entered in the template, and whitespace is used by some -- parameters (example: the numbered parameters associated with "disp=x"). local kv_pairs = {} -- table of input key:value pairs where key is a name; needed because cannot iterate parms and add new fields to it for k, v in pairs(args) do if type(k) == 'number' or k == 'test' then -- parameter "test" is reserved for testing and is not translated parms[k] = v else kv_pairs[k] = v end end if parms.test == 'wikidata' then local ulookup = function (ucode) -- Use empty table for parms so it does not accumulate results when used repeatedly. return lookup({}, ucode, 'no_combination') end return wikidata_call(parms, '_listunits', ulookup) end local success, msg = translate_parms(parms, kv_pairs) if not success then return false, msg end if parms.input then success, msg = wikidata_call(parms, '_adjustparameters', parms, 1) if not success then return false, msg end end local success, i, in_unit, in_unit_table = simple_get_values(parms) if not success then if type(i) == 'string' and i:match('^NNN+$') then -- Some infoboxes have examples like {{convert|NNN|m}} (3 or more "N"). -- Output an empty string for these. return false, { 'cvt_no_output' } end local valinfo success, valinfo, i = get_values(parms) if not success then return false, valinfo end in_unit = strip(parms[i]) i = i + 1 success, in_unit_table = lookup(parms, in_unit, 'no_combination') if not success then in_unit = in_unit or '' if parms.opt_ignore_error then -- display given unit code with no error (for use with {{val}}) in_unit_table = '' -- suppress error message and prevent processing of output unit end in_unit_table = setmetatable({ symbol = in_unit, name2 = in_unit, utype = in_unit, scale = 1, default = '', defkey = '', linkey = '', bad_mcode = in_unit_table }, unit_mt) end in_unit_table.valinfo = valinfo end if parms.test == 'msg' then -- Am testing the messages produced when no output unit is specified, and -- the input unit has a missing or invalid default. -- Set two units for testing that. -- LATER: Remove this code. if in_unit == 'chain' then in_unit_table.default = nil -- no default elseif in_unit == 'rd' then in_unit_table.default = "ft!X!m" -- an invalid expression end end in_unit_table.inout = 'in' -- this is an input unit if not parms.range then local success, inext, composite_unit = get_composite(parms, i, in_unit_table) if not success then return false, inext end if composite_unit then in_unit_table = composite_unit i = inext end end if in_unit_table.builtin == 'mach' then -- As with old template, a number following Mach as the input unit is the altitude. -- That is deprecated: should use altitude_ft=NUMBER or altitude_m=NUMBER. local success, info success = tonumber(parms[i]) -- this will often work and will give correct result for values like 2e4 without forcing output scientific notation if success then info = { value = success } else success, info = extract_number(parms, parms[i], false, true) end if success then i = i + 1 in_unit_table.altitude = info.value end end local word = strip(parms[i]) i = i + 1 local precision, is_bad_precision local function set_precision(text) local number, is_integer = get_number(text) if number then if is_integer then precision = number else precision = text is_bad_precision = true end return true -- text was used for precision, good or bad end end if word and not set_precision(word) then parms.out_unit = parms.out_unit or word if set_precision(strip(parms[i])) then i = i + 1 end end if parms.opt_adj_mid then word = parms[i] i = i + 1 if word then -- mid-text words if word:sub(1, 1) == '-' then parms.mid = word else parms.mid = ' ' .. word end end end if parms.opt_one_preunit then parms[parms.opt_flip and 'preunit2' or 'preunit1'] = preunits(1, parms[i]) i = i + 1 end if parms.disp == 'x' then -- Following is reasonably compatible with the old template. local first = parms[i] or '' local second = parms[i+1] or '' i = i + 2 if strip(first) == '' then -- user can enter '&#32;' rather than ' ' to avoid the default first = ' [&nbsp;' .. first second = '&nbsp;]' .. second end parms.joins = { first, second } elseif parms.opt_two_preunits then local p1, p2 = preunits(2, parms[i], parms[i+1]) i = i + 2 if parms.preunit1 then -- To simplify documentation, allow unlikely use of adj=pre with disp=preunit -- (however, an output unit must be specified with adj=pre and with disp=preunit). parms.preunit1 = parms.preunit1 .. p1 parms.preunit2 = p2 else parms.preunit1, parms.preunit2 = p1, p2 end end if precision == nil then if set_precision(strip(parms[i])) then i = i + 1 end end if is_bad_precision then add_warning(parms, 1, 'cvt_bad_prec', precision) else parms.precision = precision end for j = i, i + 3 do local parm = parms[j] -- warn if find a non-empty extraneous parameter if parm and parm:match('%S') then add_warning(parms, 1, 'cvt_unknown_option', parm) break end end return true, in_unit_table end local function record_default_precision(parms, out_current, precision) -- If necessary, adjust parameters and return a possibly adjusted precision. -- When converting a range of values where a default precision is required, -- that default is calculated for each value because the result sometimes -- depends on the precise input and output values. This function may cause -- the entire convert process to be repeated in order to ensure that the -- same default precision is used for each individual convert. -- If that were not done, a range like 1000 to 1000.4 may give poor results -- because the first output could be heavily rounded, while the second is not. -- For range 1000.4 to 1000, this function can give the second convert the -- same default precision that was used for the first. if not parms.opt_round_each then local maxdef = out_current.max_default_precision if maxdef then if maxdef < precision then parms.do_convert_again = true out_current.max_default_precision = precision else precision = out_current.max_default_precision end else out_current.max_default_precision = precision end end return precision end local function default_precision(parms, invalue, inclean, denominator, outvalue, in_current, out_current, extra) -- Return a default value for precision (an integer like 2, 0, -2). -- If denominator is not nil, it is the value of the denominator in inclean. -- Code follows procedures used in old template. local fudge = 1e-14 -- {{Order of magnitude}} adds this, so we do too local prec, minprec, adjust local subunit_ignore_trailing_zero local subunit_more_precision -- kludge for "in" used in input like "|2|ft|6|in" local composite = in_current.composite if composite then subunit_ignore_trailing_zero = true -- input "|2|st|10|lb" has precision 0, not -1 if composite[#composite].exception == 'subunit_more_precision' then subunit_more_precision = true -- do not use standard precision with input like "|2|ft|6|in" end end if denominator and denominator > 0 then prec = math.max(log10(denominator), 1) else -- Count digits after decimal mark, handling cases like '12.345e6'. local exponent local integer, dot, decimals, expstr = inclean:match('^(%d*)(%.?)(%d*)(.*)') local e = expstr:sub(1, 1) if e == 'e' or e == 'E' then exponent = tonumber(expstr:sub(2)) end if dot == '' then prec = subunit_ignore_trailing_zero and 0 or -integer:match('0*$'):len() else prec = #decimals end if exponent then -- So '1230' and '1.23e3' both give prec = -1, and '0.00123' and '1.23e-3' give 5. prec = prec - exponent end end if in_current.istemperature and out_current.istemperature then -- Converting between common temperatures (°C, °F, °R, K); not keVT. -- Kelvin value can be almost zero, or small but negative due to precision problems. -- Also, an input value like -300 C (below absolute zero) gives negative kelvins. -- Calculate minimum precision from absolute value. adjust = 0 local kelvin = abs((invalue - in_current.offset) * in_current.scale) if kelvin < 1e-8 then -- assume nonzero due to input or calculation precision problem minprec = 2 else minprec = 2 - floor(log10(kelvin) + fudge) -- 3 sigfigs in kelvin end else if invalue == 0 or outvalue <= 0 then -- We are never called with a negative outvalue, but it might be zero. -- This is special-cased to avoid calculation exceptions. return record_default_precision(parms, out_current, 0) end if out_current.exception == 'integer_more_precision' and floor(invalue) == invalue then -- With certain output units that sometimes give poor results -- with default rounding, use more precision when the input -- value is equal to an integer. An example of a poor result -- is when input 50 gives a smaller output than input 49.5. -- Experiment shows this helps, but it does not eliminate all -- surprises because it is not clear whether "50" should be -- interpreted as "from 45 to 55" or "from 49.5 to 50.5". adjust = -log10(in_current.scale) elseif subunit_more_precision then -- Conversion like "{{convert|6|ft|1|in|cm}}" (where subunit is "in") -- has a non-standard adjust value, to give more output precision. adjust = log10(out_current.scale) + 2 else adjust = log10(abs(invalue / outvalue)) end adjust = adjust + log10(2) -- Ensure that the output has at least two significant figures. minprec = 1 - floor(log10(outvalue) + fudge) end if extra then adjust = extra.adjust or adjust minprec = extra.minprec or minprec end return record_default_precision(parms, out_current, math.max(floor(prec + adjust), minprec)) end local function convert(parms, invalue, info, in_current, out_current) -- Convert given input value from one unit to another. -- Return output_value (a number) if a simple convert, or -- return f, t where -- f = true, t = table of information with results, or -- f = false, t = error message table. local inscale = in_current.scale local outscale = out_current.scale if not in_current.iscomplex and not out_current.iscomplex then return invalue * (inscale / outscale) -- minimize overhead for most common case end if in_current.invert or out_current.invert then -- Inverted units, such as inverse length, inverse time, or -- fuel efficiency. Built-in units do not have invert set. if (in_current.invert or 1) * (out_current.invert or 1) < 0 then return 1 / (invalue * inscale * outscale) end return invalue * (inscale / outscale) elseif in_current.offset then -- Temperature (there are no built-ins for this type of unit). if info.is_change then return invalue * (inscale / outscale) end return (invalue - in_current.offset) * (inscale / outscale) + out_current.offset else -- Built-in unit. local in_builtin = in_current.builtin local out_builtin = out_current.builtin if in_builtin and out_builtin then if in_builtin == out_builtin then return invalue end -- There are no cases (yet) where need to convert from one -- built-in unit to another, so this should never occur. return false, { 'cvt_bug_convert' } end if in_builtin == 'mach' or out_builtin == 'mach' then -- Should check that only one altitude is given but am planning to remove -- in_current.altitude (which can only occur when Mach is the input unit), -- and out_current.altitude cannot occur. local alt = parms.altitude_ft or in_current.altitude if not alt and parms.altitude_m then alt = parms.altitude_m / 0.3048 -- 1 ft = 0.3048 m end local spd = speed_of_sound(alt) if in_builtin == 'mach' then inscale = spd return invalue * (inscale / outscale) end outscale = spd local adjust = 0.1 / inscale return true, { outvalue = invalue * (inscale / outscale), adjust = log10(adjust) + log10(2), } elseif in_builtin == 'hand' then -- 1 hand = 4 inches; 1.2 hands = 6 inches. -- Decimals of a hand are only defined for the first digit, and -- the first fractional digit should be a number of inches (1, 2 or 3). -- However, this code interprets the entire fractional part as the number -- of inches / 10 (so 1.75 inches would be 0.175 hands). -- A value like 12.3 hands is exactly 12*4 + 3 inches; base default precision on that. local integer, fracpart = math.modf(invalue) local inch_value = 4 * integer + 10 * fracpart -- equivalent number of inches local factor = inscale / outscale if factor == 4 then -- Am converting to inches: show exact result, and use "inches" not "in" by default. if parms.abbr_org == nil then out_current.usename = true end local show = format('%g', abs(inch_value)) -- show and clean are unsigned if not show:find('e', 1, true) then return true, { invalue = inch_value, outvalue = inch_value, clean = show, show = show, } end end local outvalue = (integer + 2.5 * fracpart) * factor local fracstr = info.clean:match('%.(.*)') or '' local fmt if fracstr == '' then fmt = '%.0f' else fmt = '%.' .. format('%d', #fracstr - 1) .. 'f' end return true, { invalue = inch_value, clean = format(fmt, inch_value), outvalue = outvalue, minprec = 0, } end end return false, { 'cvt_bug_convert' } -- should never occur end local function user_style(parms, i) -- Return text for a user-specified style for a table cell, or '' if none, -- given i = 1 (input style) or 2 (output style). local style = parms[(i == 1) and 'stylein' or 'styleout'] if style then style = style:gsub('"', '') if style ~= '' then if style:sub(-1) ~= ';' then style = style .. ';' end return style end end return '' end local function make_table_or_sort(parms, invalue, info, in_current, scaled_top) -- Set options to handle output for a table or a sort key, or both. -- The text sort key is based on the value resulting from converting -- the input to a fake base unit with scale = 1, and other properties -- required for a conversion derived from the input unit. -- For other modules, return the sort key in a hidden span element, and -- the scaled value used to generate the sort key. -- If scaled_top is set, it is the scaled value of the numerator of a per unit -- to be combined with this unit (the denominator) to make the sort key. -- Scaling only works with units that convert with a factor (not temperature). local sortkey, scaled_value if parms.opt_sortable_on then local base = { -- a fake unit with enough fields for a valid convert scale = 1, invert = in_current.invert and 1, iscomplex = in_current.iscomplex, offset = in_current.offset and 0, } local outvalue, extra = convert(parms, invalue, info, in_current, base) if extra then outvalue = extra.outvalue end if in_current.istemperature then -- Have converted to kelvin; assume numbers close to zero have a -- rounding error and should be zero. if abs(outvalue) < 1e-12 then outvalue = 0 end end if scaled_top and outvalue ~= 0 then outvalue = scaled_top / outvalue end scaled_value = outvalue if not valid_number(outvalue) then if outvalue < 0 then sortkey = '1000000000000000000' else sortkey = '9000000000000000000' end elseif outvalue == 0 then sortkey = '5000000000000000000' else local mag = floor(log10(abs(outvalue)) + 1e-14) local prefix if outvalue > 0 then prefix = 7000 + mag else prefix = 2999 - mag outvalue = outvalue + 10^(mag+1) end sortkey = format('%d', prefix) .. format('%015.0f', floor(outvalue * 10^(14-mag))) end end local sortspan if sortkey and not parms.table_align then sortspan = parms.opt_sortable_debug and '<span data-sort-value="' .. sortkey .. '♠"><span style="border:1px solid">' .. sortkey .. '♠</span></span>' or '<span data-sort-value="' .. sortkey .. '♠"></span>' parms.join_before = sortspan end if parms.table_align then local sort if sortkey then sort = ' data-sort-value="' .. sortkey .. '"' if parms.opt_sortable_debug then parms.join_before = '<span style="border:1px solid">' .. sortkey .. '</span>' end else sort = '' end local style = 'style="text-align:' .. parms.table_align .. ';' local joins = {} for i = 1, 2 do joins[i] = (i == 1 and '' or '\n|') .. style .. user_style(parms, i) .. '"' .. sort .. '|' end parms.table_joins = joins end return sortspan, scaled_value end local cvt_to_hand local function cvtround(parms, info, in_current, out_current) -- Return true, t where t is a table with the conversion results; fields: -- show = rounded, formatted string with the result of converting value in info, -- using the rounding specified in parms. -- singular = true if result (after rounding and ignoring any negative sign) -- is "1", or like "1.00", or is a fraction with value < 1; -- (and more fields shown below, and a calculated 'absvalue' field). -- or return false, t where t is an error message table. -- Input info.clean uses en digits (it has been translated, if necessary). -- Output show uses en or non-en digits as appropriate, or can be spelled. if out_current.builtin == 'hand' then return cvt_to_hand(parms, info, in_current, out_current) end local invalue = in_current.builtin == 'hand' and info.altvalue or info.value local outvalue, extra = convert(parms, invalue, info, in_current, out_current) if parms.need_table_or_sort then parms.need_table_or_sort = nil -- process using first input value only make_table_or_sort(parms, invalue, info, in_current) end if extra then if not outvalue then return false, extra end invalue = extra.invalue or invalue outvalue = extra.outvalue end if not valid_number(outvalue) then return false, { 'cvt_invalid_num' } end local isnegative if outvalue < 0 then isnegative = true outvalue = -outvalue end local precision, show, exponent local denominator = out_current.frac if denominator then show = fraction_table(outvalue, denominator) else precision = parms.precision if not precision then if parms.sigfig then show, exponent = make_sigfig(outvalue, parms.sigfig) elseif parms.opt_round then local n = parms.opt_round if n == 0.5 then local integer, fracpart = math.modf(floor(2 * outvalue + 0.5) / 2) if fracpart == 0 then show = format('%.0f', integer) else show = format('%.1f', integer + fracpart) end else show = format('%.0f', floor((outvalue / n) + 0.5) * n) end elseif in_current.builtin == 'mach' then local sigfig = info.clean:gsub('^[0.]+', ''):gsub('%.', ''):len() + 1 show, exponent = make_sigfig(outvalue, sigfig) else local inclean = info.clean if extra then inclean = extra.clean or inclean show = extra.show end if not show then precision = default_precision(parms, invalue, inclean, info.denominator, outvalue, in_current, out_current, extra) end end end end if precision then if precision >= 0 then local fudge if precision <= 8 then -- Add a fudge to handle common cases of bad rounding due to inability -- to precisely represent some values. This makes the following work: -- {{convert|-100.1|C|K}} and {{convert|5555000|um|m|2}}. -- Old template uses #expr round, which invokes PHP round(). -- LATER: Investigate how PHP round() works. fudge = 2e-14 else fudge = 0 end local fmt = '%.' .. format('%d', precision) .. 'f' local success success, show = pcall(format, fmt, outvalue + fudge) if not success then return false, { 'cvt_big_prec', tostring(precision) } end else precision = -precision -- #digits to zero (in addition to any digits after dot) local shift = 10 ^ precision show = format('%.0f', outvalue/shift) if show ~= '0' then exponent = #show + precision end end end local t = format_number(parms, show, exponent, isnegative) if type(show) == 'string' then -- Set singular using match because on some systems 0.99999999999999999 is 1.0. if exponent then t.singular = (exponent == 1 and show:match('^10*$')) else t.singular = (show == '1' or show:match('^1%.0*$')) end else t.fraction_table = show t.singular = (outvalue <= 1) -- cannot have 'fraction == 1', but if it were possible it would be singular end t.raw_absvalue = outvalue -- absolute value before rounding return true, setmetatable(t, { __index = function (self, key) if key == 'absvalue' then -- Calculate absolute value after rounding, if needed. local clean, exponent = rawget(self, 'clean'), rawget(self, 'exponent') local value = tonumber(clean) -- absolute value (any negative sign has been ignored) if exponent then value = value * 10^exponent end rawset(self, key, value) return value end end }) end function cvt_to_hand(parms, info, in_current, out_current) -- Convert input to hands, inches. -- Return true, t where t is a table with the conversion results; -- or return false, t where t is an error message table. if parms.abbr_org == nil then out_current.usename = true -- default is to show name not symbol end local precision = parms.precision local frac = out_current.frac if not frac and precision and precision > 1 then frac = (precision == 2) and 2 or 4 end local out_next = out_current.out_next if out_next then -- Use magic knowledge to determine whether the next unit is inches without requiring i18n. -- The following ensures that when the output combination "hand in" is used, the inches -- value is rounded to match the hands value. Also, displaying say "61½" instead of 61.5 -- is better as 61.5 implies the value is not 61.4. if out_next.exception == 'subunit_more_precision' then out_next.frac = frac end end -- Convert to inches; calculate hands from that. local dummy_unit_table = { scale = out_current.scale / 4, frac = frac } local success, outinfo = cvtround(parms, info, in_current, dummy_unit_table) if not success then return false, outinfo end local tfrac = outinfo.fraction_table local inches = outinfo.raw_absvalue if tfrac then inches = floor(inches) -- integer part only; fraction added later else inches = floor(inches + 0.5) -- a hands measurement never shows decimals of an inch end local hands, inches = divide(inches, 4) outinfo.absvalue = hands + inches/4 -- supposed to be the absolute rounded value, but this is close enough local inchstr = tostring(inches) -- '0', '1', '2' or '3' if precision and precision <= 0 then -- using negative or 0 for precision rounds to nearest hand hands = floor(outinfo.raw_absvalue/4 + 0.5) inchstr = '' elseif tfrac then -- Always show an integer before fraction (like "15.0½") because "15½" means 15-and-a-half hands. inchstr = numdot .. format_fraction(parms, 'out', false, inchstr, tfrac.numstr, tfrac.denstr) else inchstr = numdot .. from_en(inchstr) end outinfo.show = outinfo.sign .. with_separator(parms, format('%.0f', hands)) .. inchstr return true, outinfo end local function evaluate_condition(value, condition) -- Return true or false from applying a conditional expression to value, -- or throw an error if invalid. -- A very limited set of expressions is supported: -- v < 9 -- v * 9 < 9 -- where -- 'v' is replaced with value -- 9 is any number (as defined by Lua tonumber) -- only en digits are accepted -- '<' can also be '<=' or '>' or '>=' -- In addition, the following form is supported: -- LHS and RHS -- where -- LHS, RHS = any of above expressions. local function compare(value, text) local arithop, factor, compop, limit = text:match('^%s*v%s*([*]?)(.-)([<>]=?)(.*)$') if arithop == nil then error('Invalid default expression', 0) elseif arithop == '*' then factor = tonumber(factor) if factor == nil then error('Invalid default expression', 0) end value = value * factor end limit = tonumber(limit) if limit == nil then error('Invalid default expression', 0) end if compop == '<' then return value < limit elseif compop == '<=' then return value <= limit elseif compop == '>' then return value > limit elseif compop == '>=' then return value >= limit end error('Invalid default expression', 0) -- should not occur end local lhs, rhs = condition:match('^(.-%W)and(%W.*)') if lhs == nil then return compare(value, condition) end return compare(value, lhs) and compare(value, rhs) end local function get_default(value, unit_table) -- Return true, s where s = name of unit's default output unit, -- or return false, t where t is an error message table. -- Some units have a default that depends on the input value -- (the first value if a range of values is used). -- If '!' is in the default, the first bang-delimited field is an -- expression that uses 'v' to represent the input value. -- Example: 'v < 120 ! small ! big ! suffix' (suffix is optional) -- evaluates 'v < 120' as a boolean with result -- 'smallsuffix' if (value < 120), or 'bigsuffix' otherwise. -- Input must use en digits and '.' decimal mark. local default = data_code.default_exceptions[unit_table.defkey or unit_table.symbol] or unit_table.default if not default then local per = unit_table.per if per then local function a_default(v, u) local success, ucode = get_default(v, u) if not success then return '?' -- an unlikely error has occurred; will cause lookup of default to fail end -- Attempt to use only the first unit if a combination or output multiple. -- This is not bulletproof but should work for most cases. -- Where it does not work, the convert will need to specify the wanted output unit. local t = all_units[ucode] if t then local combo = t.combination if combo then -- For a multiple like ftin, the "first" unit (ft) is last in the combination. local i = t.multiple and table_len(combo) or 1 ucode = combo[i] end else -- Try for an automatically generated combination. local item = ucode:match('^(.-)%+') or ucode:match('^(%S+)%s') if all_units[item] then return item end end return ucode end local unit1, unit2 = per[1], per[2] local def1 = (unit1 and a_default(value, unit1) or unit_table.vprefix or '') local def2 = a_default(1, unit2) -- 1 because per unit of denominator return true, def1 .. '/' .. def2 end return false, { 'cvt_no_default', unit_table.symbol } end if default:find('!', 1, true) == nil then return true, default end local t = split(default, '!') if #t == 3 or #t == 4 then local success, result = pcall(evaluate_condition, value, t[1]) if success then default = result and t[2] or t[3] if #t == 4 then default = default .. t[4] end return true, default end end return false, { 'cvt_bad_default', unit_table.symbol } end local linked_pages -- to record linked pages so will not link to the same page more than once local function unlink(unit_table) -- Forget that the given unit has previously been linked (if it has). -- That is needed when processing a range of inputs or outputs when an id -- for the first range value may have been evaluated, but only an id for -- the last value is displayed, and that id may need to be linked. linked_pages[unit_table.unitcode or unit_table] = nil end local function make_link(link, id, unit_table) -- Return wikilink "[[link|id]]", possibly abbreviated as in examples: -- [[Mile|mile]] --> [[mile]] -- [[Mile|miles]] --> [[mile]]s -- However, just id is returned if: -- * no link given (so caller does not need to check if a link was defined); or -- * link has previously been used during the current convert (to avoid overlinking). local link_key if unit_table then link_key = unit_table.unitcode or unit_table else link_key = link end if not link or link == '' or linked_pages[link_key] then return id end linked_pages[link_key] = true -- Following only works for language en, but it should be safe on other wikis, -- and overhead of doing it generally does not seem worthwhile. local l = link:sub(1, 1):lower() .. link:sub(2) if link == id or l == id then return '[[' .. id .. ']]' elseif link .. 's' == id or l .. 's' == id then return '[[' .. id:sub(1, -2) .. ']]s' else return '[[' .. link .. '|' .. id .. ']]' end end local function variable_name(clean, unit_table) -- For slwiki, a unit name depends on the value. -- Parameter clean is the unsigned rounded value in en digits, as a string. -- Value Source Example for "m" -- integer 1: name1 meter (also is the name of the unit) -- integer 2: var{1} metra -- integer 3 and 4: var{2} metri -- integer else: var{3} metrov (0 and 5 or more) -- real/fraction: var{4} metra -- var{i} means the i'th field in unit_table.varname if it exists and has -- an i'th field, otherwise name2. -- Fields are separated with "!" and are not empty. -- A field for a unit using an SI prefix has the prefix name inserted, -- replacing '#' if found, or before the field otherwise. local vname if clean == '1' then vname = unit_table.name1 elseif unit_table.varname then local i if clean == '2' then i = 1 elseif clean == '3' or clean == '4' then i = 2 elseif clean:find('.', 1, true) then i = 4 else i = 3 end if i > 1 and varname == 'pl' then i = i - 1 end vname = split(unit_table.varname, '!')[i] end if vname then local si_name = rawget(unit_table, 'si_name') or '' local pos = vname:find('#', 1, true) if pos then vname = vname:sub(1, pos - 1) .. si_name .. vname:sub(pos + 1) else vname = si_name .. vname end return vname end return unit_table.name2 end local function linked_id(parms, unit_table, key_id, want_link, clean) -- Return final unit id (symbol or name), optionally with a wikilink, -- and update unit_table.sep if required. -- key_id is one of: 'symbol', 'sym_us', 'name1', 'name1_us', 'name2', 'name2_us'. local abbr_on = (key_id == 'symbol' or key_id == 'sym_us') if abbr_on and want_link then local symlink = rawget(unit_table, 'symlink') if symlink then return symlink -- for exceptions that have the linked symbol built-in end end local multiplier = rawget(unit_table, 'multiplier') local per = unit_table.per if per then local paren1, paren2 = '', '' -- possible parentheses around bottom unit local unit1 = per[1] -- top unit_table, or nil local unit2 = per[2] -- bottom unit_table if abbr_on then if not unit1 then unit_table.sep = '' -- no separator in "$2/acre" end if not want_link then local symbol = unit_table.symbol_raw if symbol then return symbol -- for exceptions that have the symbol built-in end end if (unit2.symbol):find('⋅', 1, true) then paren1, paren2 = '(', ')' end end local key_id2 -- unit2 is always singular if key_id == 'name2' then key_id2 = 'name1' elseif key_id == 'name2_us' then key_id2 = 'name1_us' else key_id2 = key_id end local result if abbr_on then result = '/' elseif omitsep then result = per_word elseif unit1 then result = ' ' .. per_word .. ' ' else result = per_word .. ' ' end if want_link and unit_table.link then if abbr_on or not varname then result = (unit1 and linked_id(parms, unit1, key_id, false, clean) or '') .. result .. linked_id(parms, unit2, key_id2, false, '1') else result = (unit1 and variable_name(clean, unit1) or '') .. result .. variable_name('1', unit2) end if omit_separator(result) then unit_table.sep = '' end return make_link(unit_table.link, result, unit_table) end if unit1 then result = linked_id(parms, unit1, key_id, want_link, clean) .. result if unit1.sep then unit_table.sep = unit1.sep end elseif omitsep then unit_table.sep = '' end return result .. paren1 .. linked_id(parms, unit2, key_id2, want_link, '1') .. paren2 end if multiplier then -- A multiplier (like "100" in "100km") forces the unit to be plural. multiplier = from_en(multiplier) if not omitsep then multiplier = multiplier .. (abbr_on and '&nbsp;' or ' ') end if not abbr_on then if key_id == 'name1' then key_id = 'name2' elseif key_id == 'name1_us' then key_id = 'name2_us' end end else multiplier = '' end local id = unit_table.fixed_name or ((varname and not abbr_on) and variable_name(clean, unit_table) or unit_table[key_id]) if omit_separator(id) then unit_table.sep = '' end if want_link then local link = data_code.link_exceptions[unit_table.linkey or unit_table.symbol] or unit_table.link if link then local before = '' local i = unit_table.customary if i == 1 and parms.opt_sp_us then i = 2 -- show "U.S." not "US" end if i == 3 and abbr_on then i = 4 -- abbreviate "imperial" to "imp" end local customary = text_code.customary_units[i] if customary then -- LATER: This works for language en only, but it's esoteric so ignore for now. local pertext if id:sub(1, 1) == '/' then -- Want unit "/USgal" to display as "/U.S. gal", not "U.S. /gal". pertext = '/' id = id:sub(2) elseif id:sub(1, 4) == 'per ' then -- Similarly want "per U.S. gallon", not "U.S. per gallon" (but in practice this is unlikely to be used). pertext = 'per ' id = id:sub(5) else pertext = '' end -- Omit any "US"/"U.S."/"imp"/"imperial" from start of id since that will be inserted. local removes = (i < 3) and { 'US&nbsp;', 'US ', 'U.S.&nbsp;', 'U.S. ' } or { 'imp&nbsp;', 'imp ', 'imperial ' } for _, prefix in ipairs(removes) do local plen = #prefix if id:sub(1, plen) == prefix then id = id:sub(plen + 1) break end end before = pertext .. make_link(customary.link, customary[1]) .. ' ' end id = before .. make_link(link, id, unit_table) end end return multiplier .. id end local function make_id(parms, which, unit_table) -- Return id, f where -- id = unit name or symbol, possibly modified -- f = true if id is a name, or false if id is a symbol -- using the value for index 'which', and for 'in' or 'out' (unit_table.inout). -- Result is '' if no symbol/name is to be used. -- In addition, set unit_table.sep = ' ' or '&nbsp;' or '' -- (the separator that caller will normally insert before the id). if parms.opt_values then unit_table.sep = '' return '' end local inout = unit_table.inout local info = unit_table.valinfo[which] local abbr_org = parms.abbr_org local adjectival = parms.opt_adjectival local lk = parms.lk local want_link = (lk == 'on' or lk == inout) local usename = unit_table.usename local singular = info.singular local want_name if usename then want_name = true else if abbr_org == nil then if parms.wantname then want_name = true end if unit_table.usesymbol then want_name = false end end if want_name == nil then local abbr = parms.abbr if abbr == 'on' or abbr == inout or (abbr == 'mos' and inout == 'out') then want_name = false else want_name = true end end end local key if want_name then if lk == nil and unit_table.builtin == 'hand' then want_link = true end if parms.opt_use_nbsp then unit_table.sep = '&nbsp;' else unit_table.sep = ' ' end if parms.opt_singular then local value if inout == 'in' then value = info.value else value = info.absvalue end if value then -- some unusual units do not always set value field value = abs(value) singular = (0 < value and value < 1.0001) end end if unit_table.engscale then -- engscale: so "|1|e3kg" gives "1 thousand kilograms" (plural) singular = false end key = (adjectival or singular) and 'name1' or 'name2' if parms.opt_sp_us then key = key .. '_us' end else if unit_table.builtin == 'hand' then if parms.opt_hand_hh then unit_table.symbol = 'hh' -- LATER: might want i18n applied to this end end unit_table.sep = '&nbsp;' key = parms.opt_sp_us and 'sym_us' or 'symbol' end return linked_id(parms, unit_table, key, want_link, info.clean), want_name end local function decorate_value(parms, unit_table, which, number_word) -- If needed, update unit_table so values will be shown with extra information. -- For consistency with the old template (but different from fmtpower), -- the style to display powers of 10 includes "display:none" to allow some -- browsers to copy, for example, "10³" as "10^3", rather than as "103". local info local engscale = unit_table.engscale local prefix = unit_table.vprefix if engscale or prefix then info = unit_table.valinfo[which] if info.decorated then return -- do not redecorate if repeating convert end info.decorated = true if engscale then local inout = unit_table.inout local abbr = parms.abbr if (abbr == 'on' or abbr == inout) and not parms.number_word then info.show = info.show .. '<span style="margin-left:0.2em">×<span style="margin-left:0.1em">' .. from_en('10') .. '</span></span><s style="display:none">^</s><sup>' .. from_en(tostring(engscale.exponent)) .. '</sup>' elseif number_word then local number_id local lk = parms.lk if lk == 'on' or lk == inout then number_id = make_link(engscale.link, engscale[1]) else number_id = engscale[1] end -- WP:NUMERAL recommends "&nbsp;" in values like "12 million". info.show = info.show .. (parms.opt_adjectival and '-' or '&nbsp;') .. number_id end end if prefix then info.show = prefix .. info.show end end end local function process_input(parms, in_current) -- Processing required once per conversion. -- Return block of text to represent input (value/unit). if parms.opt_output_only or parms.opt_output_number_only or parms.opt_output_unit_only then parms.joins = { '', '' } return '' end local first_unit local composite = in_current.composite -- nil or table of units if composite then first_unit = composite[1] else first_unit = in_current end local id1, want_name = make_id(parms, 1, first_unit) local sep = first_unit.sep -- separator between value and unit, set by make_id local preunit = parms.preunit1 if preunit then sep = '' -- any separator is included in preunit else preunit = '' end if parms.opt_input_unit_only then parms.joins = { '', '' } if composite then local parts = { id1 } for i, unit in ipairs(composite) do if i > 1 then table.insert(parts, (make_id(parms, 1, unit))) end end id1 = table.concat(parts, ' ') end if want_name and parms.opt_adjectival then return preunit .. hyphenated(id1) end return preunit .. id1 end if parms.opt_also_symbol and not composite and not parms.opt_flip then local join1 = parms.joins[1] if join1 == ' (' or join1 == ' [' then parms.joins = { ' [' .. first_unit[parms.opt_sp_us and 'sym_us' or 'symbol'] .. ']' .. join1 , parms.joins[2] } end end if in_current.builtin == 'mach' and first_unit.sep ~= '' then -- '' means omitsep with non-enwiki name local prefix = id1 .. '&nbsp;' local range = parms.range local valinfo = first_unit.valinfo local result = prefix .. valinfo[1].show if range then -- For simplicity and because more not needed, handle one range item only. local prefix2 = make_id(parms, 2, first_unit) .. '&nbsp;' result = range_text(range[1], want_name, parms, result, prefix2 .. valinfo[2].show, 'in', {spaced=true}) end return preunit .. result end if composite then -- Simplify: assume there is no range, and no decoration. local mid = (not parms.opt_flip) and parms.mid or '' local sep1 = '&nbsp;' local sep2 = ' ' if parms.opt_adjectival and want_name then sep1 = '-' sep2 = '-' end if omitsep and sep == '' then -- Testing the id of the most significant unit should be sufficient. sep1 = '' sep2 = '' end local parts = { first_unit.valinfo[1].show .. sep1 .. id1 } for i, unit in ipairs(composite) do if i > 1 then table.insert(parts, unit.valinfo[1].show .. sep1 .. (make_id(parms, 1, unit))) end end return table.concat(parts, sep2) .. mid end local add_unit = (parms.abbr == 'mos') or parms[parms.opt_flip and 'out_range_x' or 'in_range_x'] or (not want_name and parms.abbr_range_x) local range = parms.range if range and not add_unit then unlink(first_unit) end local id = range and make_id(parms, range.n + 1, first_unit) or id1 local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, 'in') if was_hyphenated then add_unit = false end local result local valinfo = first_unit.valinfo if range then for i = 0, range.n do local number_word if i == range.n then add_unit = false number_word = true end decorate_value(parms, first_unit, i+1, number_word) local show = valinfo[i+1].show if add_unit then show = show .. first_unit.sep .. (i == 0 and id1 or make_id(parms, i+1, first_unit)) end if i == 0 then result = show else result = range_text(range[i], want_name, parms, result, show, 'in') end end else decorate_value(parms, first_unit, 1, true) result = valinfo[1].show end return result .. preunit .. extra end local function process_one_output(parms, out_current) -- Processing required for each output unit. -- Return block of text to represent output (value/unit). local inout = out_current.inout -- normally 'out' but can be 'in' for order=out local id1, want_name = make_id(parms, 1, out_current) local sep = out_current.sep -- set by make_id local preunit = parms.preunit2 if preunit then sep = '' -- any separator is included in preunit else preunit = '' end if parms.opt_output_unit_only then if want_name and parms.opt_adjectival then return preunit .. hyphenated(id1) end return preunit .. id1 end if out_current.builtin == 'mach' and out_current.sep ~= '' then -- '' means omitsep with non-enwiki name local prefix = id1 .. '&nbsp;' local range = parms.range local valinfo = out_current.valinfo local result = prefix .. valinfo[1].show if range then -- For simplicity and because more not needed, handle one range item only. result = range_text(range[1], want_name, parms, result, prefix .. valinfo[2].show, inout, {spaced=true}) end return preunit .. result end local add_unit = (parms[parms.opt_flip and 'in_range_x' or 'out_range_x'] or (not want_name and parms.abbr_range_x)) and not parms.opt_output_number_only local range = parms.range if range and not add_unit then unlink(out_current) end local id = range and make_id(parms, range.n + 1, out_current) or id1 local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, inout) if was_hyphenated then add_unit = false end local result local valinfo = out_current.valinfo if range then for i = 0, range.n do local number_word if i == range.n then add_unit = false number_word = true end decorate_value(parms, out_current, i+1, number_word) local show = valinfo[i+1].show if add_unit then show = show .. out_current.sep .. (i == 0 and id1 or make_id(parms, i+1, out_current)) end if i == 0 then result = show else result = range_text(range[i], want_name, parms, result, show, inout) end end else decorate_value(parms, out_current, 1, true) result = valinfo[1].show end if parms.opt_output_number_only then return result end return result .. preunit .. extra end local function make_output_single(parms, in_unit_table, out_unit_table) -- Return true, item where item = wikitext of the conversion result -- for a single output (which is not a combination or a multiple); -- or return false, t where t is an error message table. if parms.opt_order_out and in_unit_table.unitcode == out_unit_table.unitcode then out_unit_table.valinfo = in_unit_table.valinfo else out_unit_table.valinfo = collection() for _, v in ipairs(in_unit_table.valinfo) do local success, info = cvtround(parms, v, in_unit_table, out_unit_table) if not success then return false, info end out_unit_table.valinfo:add(info) end end return true, process_one_output(parms, out_unit_table) end local function make_output_multiple(parms, in_unit_table, out_unit_table) -- Return true, item where item = wikitext of the conversion result -- for an output which is a multiple (like 'ftin'); -- or return false, t where t is an error message table. local inout = out_unit_table.inout -- normally 'out' but can be 'in' for order=out local multiple = out_unit_table.multiple -- table of scaling factors (will not be nil) local combos = out_unit_table.combination -- table of unit tables (will not be nil) local abbr = parms.abbr local abbr_org = parms.abbr_org local disp = parms.disp local want_name = (abbr_org == nil and (disp == 'or' or disp == 'slash')) or not (abbr == 'on' or abbr == inout or abbr == 'mos') local want_link = (parms.lk == 'on' or parms.lk == inout) local mid = parms.opt_flip and parms.mid or '' local sep1 = '&nbsp;' local sep2 = ' ' if parms.opt_adjectival and want_name then sep1 = '-' sep2 = '-' end local do_spell = parms.opt_spell_out parms.opt_spell_out = nil -- so the call to cvtround does not spell the value local function make_result(info, isfirst) local fmt, outvalue, sign local results = {} for i = 1, #combos do local tfrac, thisvalue, strforce local out_current = combos[i] out_current.inout = inout local scale = multiple[i] if i == 1 then -- least significant unit ('in' from 'ftin') local decimals out_current.frac = out_unit_table.frac local success, outinfo = cvtround(parms, info, in_unit_table, out_current) if not success then return false, outinfo end if isfirst then out_unit_table.valinfo = { outinfo } -- in case output value of first least significant unit is needed end sign = outinfo.sign tfrac = outinfo.fraction_table if outinfo.is_scientific then strforce = outinfo.show decimals = '' elseif tfrac then decimals = '' else local show = outinfo.show -- number as a string in local language local p1, p2 = show:find(numdot, 1, true) decimals = p1 and show:sub(p2 + 1) or '' -- text after numdot, if any end fmt = '%.' .. ulen(decimals) .. 'f' -- to reproduce precision if decimals == '' then if tfrac then outvalue = floor(outinfo.raw_absvalue) -- integer part only; fraction added later else outvalue = floor(outinfo.raw_absvalue + 0.5) -- keep all integer digits of least significant unit end else outvalue = outinfo.absvalue end end if scale then outvalue, thisvalue = divide(outvalue, scale) else thisvalue = outvalue end local id if want_name then if varname then local clean if strforce or tfrac then clean = '.1' -- dummy value to force name for floating point else clean = format(fmt, thisvalue) end id = variable_name(clean, out_current) else local key = 'name2' if parms.opt_adjectival then key = 'name1' elseif tfrac then if thisvalue == 0 then key = 'name1' end elseif parms.opt_singular then if 0 < thisvalue and thisvalue < 1.0001 then key = 'name1' end else if thisvalue == 1 then key = 'name1' end end id = out_current[key] end else id = out_current['symbol'] end if i == 1 and omit_separator(id) then -- Testing the id of the least significant unit should be sufficient. sep1 = '' sep2 = '' end if want_link then local link = out_current.link if link then id = make_link(link, id, out_current) end end local strval local spell_inout = (i == #combos or outvalue == 0) and inout or '' -- trick so the last value processed (first displayed) has uppercase, if requested if strforce and outvalue == 0 then sign = '' -- any sign is in strforce strval = strforce -- show small values in scientific notation; will only use least significant unit elseif tfrac then local wholestr = (thisvalue > 0) and tostring(thisvalue) or nil strval = format_fraction(parms, spell_inout, false, wholestr, tfrac.numstr, tfrac.denstr, do_spell) else strval = (thisvalue == 0) and from_en('0') or with_separator(parms, format(fmt, thisvalue)) if do_spell then strval = spell_number(parms, spell_inout, strval) or strval end end table.insert(results, strval .. sep1 .. id) if outvalue == 0 then break end fmt = '%.0f' -- only least significant unit can have a non-integral value end local reversed, count = {}, #results for i = 1, count do reversed[i] = results[count + 1 - i] end return true, sign .. table.concat(reversed, sep2) end local valinfo = in_unit_table.valinfo local success, result = make_result(valinfo[1], true) if not success then return false, result end local range = parms.range if range then for i = 1, range.n do local success, result2 = make_result(valinfo[i+1]) if not success then return false, result2 end result = range_text(range[i], want_name, parms, result, result2, inout, {spaced=true}) end end return true, result .. mid end local function process(parms, in_unit_table, out_unit_table) -- Return true, s, outunit where s = final wikitext result, -- or return false, t where t is an error message table. linked_pages = {} local success, bad_output local bad_input_mcode = in_unit_table.bad_mcode -- nil if input unit is a valid convert unit local out_unit = parms.out_unit if out_unit == nil or out_unit == '' or type(out_unit) == 'function' then if bad_input_mcode or parms.opt_input_unit_only then bad_output = '' else local getdef = type(out_unit) == 'function' and out_unit or get_default success, out_unit = getdef(in_unit_table.valinfo[1].value, in_unit_table) parms.out_unit = out_unit if not success then bad_output = out_unit end end end if not bad_output and not out_unit_table then success, out_unit_table = lookup(parms, out_unit, 'any_combination') if success then local mismatch = check_mismatch(in_unit_table, out_unit_table) if mismatch then bad_output = mismatch end else bad_output = out_unit_table end end local lhs, rhs local flipped = parms.opt_flip and not bad_input_mcode if bad_output then rhs = (bad_output == '') and '' or message(parms, bad_output) elseif parms.opt_input_unit_only then rhs = '' else local combos -- nil (for 'ft' or 'ftin'), or table of unit tables (for 'm ft') if not out_unit_table.multiple then -- nil/false ('ft' or 'm ft'), or table of factors ('ftin') combos = out_unit_table.combination end local frac = parms.frac -- nil or denominator of fraction for output values if frac then -- Apply fraction to the unit (if only one), or to non-SI units (if a combination), -- except that if a precision is also specified, the fraction only applies to -- the hand unit; that allows the following result: -- {{convert|156|cm|in hand|1|frac=2}} → 156 centimetres (61.4 in; 15.1½ hands) -- However, the following is handled elsewhere as a special case: -- {{convert|156|cm|hand in|1|frac=2}} → 156 centimetres (15.1½ hands; 61½ in) if combos then local precision = parms.precision for _, unit in ipairs(combos) do if unit.builtin == 'hand' or (not precision and not unit.prefixes) then unit.frac = frac end end else out_unit_table.frac = frac end end local outputs = {} local imax = combos and #combos or 1 -- 1 (single unit) or number of unit tables if imax == 1 then parms.opt_order_out = nil -- only useful with an output combination end if not flipped and not parms.opt_order_out then -- Process left side first so any duplicate links (from lk=on) are suppressed -- on right. Example: {{convert|28|e9pc|e9ly|abbr=off|lk=on}} lhs = process_input(parms, in_unit_table) end for i = 1, imax do local success, item local out_current = combos and combos[i] or out_unit_table out_current.inout = 'out' if i == 1 then if imax > 1 and out_current.builtin == 'hand' then out_current.out_next = combos[2] -- built-in hand can influence next unit in a combination end if parms.opt_order_out then out_current.inout = 'in' end end if out_current.multiple then success, item = make_output_multiple(parms, in_unit_table, out_current) else success, item = make_output_single(parms, in_unit_table, out_current) end if not success then return false, item end outputs[i] = item end if parms.opt_order_out then lhs = outputs[1] table.remove(outputs, 1) end local sep = parms.table_joins and parms.table_joins[2] or parms.join_between rhs = table.concat(outputs, sep) end if flipped or not lhs then local input = process_input(parms, in_unit_table) if flipped then lhs = rhs rhs = input else lhs = input end end if parms.join_before then lhs = parms.join_before .. lhs end local wikitext if bad_input_mcode then if bad_input_mcode == '' then wikitext = lhs else wikitext = lhs .. message(parms, bad_input_mcode) end elseif parms.table_joins then wikitext = parms.table_joins[1] .. lhs .. parms.table_joins[2] .. rhs else wikitext = lhs .. parms.joins[1] .. rhs .. parms.joins[2] end if parms.warnings and not bad_input_mcode then wikitext = wikitext .. parms.warnings end return true, get_styles(parms) .. wikitext, out_unit_table end local function main_convert(frame) -- Do convert, and if needed, do it again with higher default precision. local parms = { frame = frame } -- will hold template arguments, after translation set_config(frame.args) local success, result = get_parms(parms, frame:getParent().args) if success then if type(result) ~= 'table' then return tostring(result) end local in_unit_table = result local out_unit_table for _ = 1, 2 do -- use counter so cannot get stuck repeating convert success, result, out_unit_table = process(parms, in_unit_table, out_unit_table) if success and parms.do_convert_again then parms.do_convert_again = false else break end end end -- If input=x gives a problem, the result should be just the user input -- (if x is a property like P123 it has been replaced with ''). -- An unknown input unit would display the input and an error message -- with success == true at this point. -- Also, can have success == false with a message that outputs an empty string. if parms.input_text then if success and not parms.have_problem then return result end local cat if parms.tracking then -- Add a tracking category using the given text as the category sort key. -- There is currently only one type of tracking, but in principle multiple -- items could be tracked, using different sort keys for convenience. cat = wanted_category('tracking', parms.tracking) end return parms.input_text .. (cat or '') end return success and result or message(parms, result) end local function _unit(unitcode, options) -- Helper function for Module:Val to look up a unit. -- Parameter unitcode must be a string to identify the wanted unit. -- Parameter options must be nil or a table with optional fields: -- value = number (for sort key; default value is 1) -- scaled_top = nil for a normal unit, or a number for a unit which is -- the denominator of a per unit (for sort key) -- si = { 'symbol', 'link' } -- (a table with two strings) to make an SI unit -- that will be used for the look up -- link = true if result should be [[linked]] -- sort = 'on' or 'debug' if result should include a sort key in a -- span element ('debug' makes the key visible) -- name = true for the name of the unit instead of the symbol -- us = true for the US spelling of the unit, if any -- Return nil if unitcode is not a non-empty string. -- Otherwise return a table with fields: -- text = requested symbol or name of unit, optionally linked -- scaled_value = input value adjusted by unit scale; used for sort key -- sortspan = span element with sort key like that provided by {{ntsh}}, -- calculated from the result of converting value -- to a base unit with scale 1. -- unknown = true if the unitcode was not known unitcode = strip(unitcode) if unitcode == nil or unitcode == '' then return nil end set_config({}) linked_pages = {} options = options or {} local parms = { abbr = options.name and 'off' or 'on', lk = options.link and 'on' or nil, opt_sp_us = options.us and true or nil, opt_ignore_error = true, -- do not add pages using this function to 'what links here' for Module:Convert/extra opt_sortable_on = options.sort == 'on' or options.sort == 'debug', opt_sortable_debug = options.sort == 'debug', } if options.si then -- Make a dummy table of units (just one unit) for lookup to use. -- This makes lookup recognize any SI prefix in the unitcode. local symbol = options.si[1] or '?' parms.unittable = { [symbol] = { _name1 = symbol, _name2 = symbol, _symbol = symbol, utype = symbol, scale = symbol == 'g' and 0.001 or 1, prefixes = 1, default = symbol, link = options.si[2], }} end local success, unit_table = lookup(parms, unitcode, 'no_combination') if not success then unit_table = setmetatable({ symbol = unitcode, name2 = unitcode, utype = unitcode, scale = 1, default = '', defkey = '', linkey = '' }, unit_mt) end local value = tonumber(options.value) or 1 local clean = tostring(abs(value)) local info = { value = value, altvalue = value, singular = (clean == '1'), clean = clean, show = clean, } unit_table.inout = 'in' unit_table.valinfo = { info } local sortspan, scaled_value if options.sort then sortspan, scaled_value = make_table_or_sort(parms, value, info, unit_table, options.scaled_top) end return { text = make_id(parms, 1, unit_table), sortspan = sortspan, scaled_value = scaled_value, unknown = not success and true or nil, } end return { convert = main_convert, _unit = _unit } da3d419635c73ffef0a5bcc2a7d6620979271521 Module:Convert/data 828 47 110 109 2022-09-04T15:24:31Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- Conversion data used by [[Module:Convert]] which uses mw.loadData() for -- read-only access to this module so that it is loaded only once per page. -- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki. -- -- These data tables follow: -- all_units all properties for a unit, including default output -- default_exceptions exceptions for default output ('kg' and 'g' have different defaults) -- link_exceptions exceptions for links ('kg' and 'g' have different links) -- -- These tables are generated by a script which reads the wikitext of a page that -- documents the required properties of each unit; see [[:en:Module:Convert/doc]]. --------------------------------------------------------------------------- -- Do not change the data in this table because it is created by running -- -- a script that reads the wikitext from a wiki page (see note above). -- --------------------------------------------------------------------------- local all_units = { ["Gy"] = { _name1 = "gray", _symbol = "Gy", utype = "absorbed radiation dose", scale = 1, prefixes = 1, default = "rad", link = "Gray (unit)", }, ["rad"] = { _name1 = "rad", _symbol = "rad", utype = "absorbed radiation dose", scale = 0.01, prefixes = 1, default = "Gy", link = "Rad (unit)", }, ["cm/s2"] = { name1 = "centimetre per second squared", name1_us = "centimeter per second squared", name2 = "centimetres per second squared", name2_us = "centimeters per second squared", symbol = "cm/s<sup>2</sup>", utype = "acceleration", scale = 0.01, default = "ft/s2", link = "Gal (unit)", }, ["ft/s2"] = { name1 = "foot per second squared", name2 = "feet per second squared", symbol = "ft/s<sup>2</sup>", utype = "acceleration", scale = 0.3048, default = "m/s2", }, ["g0"] = { name1 = "standard gravity", name2 = "standard gravities", symbol = "''g''<sub>0</sub>", utype = "acceleration", scale = 9.80665, default = "m/s2", }, ["g-force"] = { name2 = "''g''", symbol = "''g''", utype = "acceleration", scale = 9.80665, default = "m/s2", link = "g-force", }, ["km/hs"] = { name1 = "kilometre per hour per second", name1_us = "kilometer per hour per second", name2 = "kilometres per hour per second", name2_us = "kilometers per hour per second", symbol = "km/(h⋅s)", utype = "acceleration", scale = 0.27777777777777779, default = "mph/s", link = "Acceleration", }, ["km/s2"] = { name1 = "kilometre per second squared", name1_us = "kilometer per second squared", name2 = "kilometres per second squared", name2_us = "kilometers per second squared", symbol = "km/s<sup>2</sup>", utype = "acceleration", scale = 1000, default = "mph/s", link = "Acceleration", }, ["m/s2"] = { name1 = "metre per second squared", name1_us = "meter per second squared", name2 = "metres per second squared", name2_us = "meters per second squared", symbol = "m/s<sup>2</sup>", utype = "acceleration", scale = 1, default = "ft/s2", }, ["mph/s"] = { name1 = "mile per hour per second", name2 = "miles per hour per second", symbol = "mph/s", utype = "acceleration", scale = 0.44704, default = "km/hs", link = "Acceleration", }, ["km/h/s"] = { target = "km/hs", }, ["standard gravity"] = { target = "g0", }, ["1000sqft"] = { name1 = "thousand square feet", name2 = "thousand square feet", symbol = "1000&nbsp;sq&nbsp;ft", utype = "area", scale = 92.90304, default = "m2", link = "Square foot", }, ["a"] = { _name1 = "are", _symbol = "a", utype = "area", scale = 100, prefixes = 1, default = "sqft", link = "Hectare#Are", }, ["acre"] = { symbol = "acre", usename = 1, utype = "area", scale = 4046.8564224, default = "ha", subdivs = { ["rood"] = { 4, default = "ha" }, ["sqperch"] = { 160, default = "ha" } }, }, ["acre-sing"] = { target = "acre", }, ["arpent"] = { symbol = "arpent", usename = 1, utype = "area", scale = 3418.89, default = "ha", }, ["cda"] = { name1 = "cuerda", symbol = "cda", utype = "area", scale = 3930.395625, default = "ha acre", }, ["daa"] = { name1 = "decare", symbol = "daa", utype = "area", scale = 1000, default = "km2 sqmi", }, ["dunam"] = { symbol = "dunam", usename = 1, utype = "area", scale = 1000, default = "km2 sqmi", }, ["dunum"] = { symbol = "dunum", usename = 1, utype = "area", scale = 1000, default = "km2 sqmi", link = "Dunam", }, ["ha"] = { name1 = "hectare", symbol = "ha", utype = "area", scale = 10000, default = "acre", }, ["hectare"] = { name1 = "hectare", symbol = "ha", usename = 1, utype = "area", scale = 10000, default = "acre", }, ["Irish acre"] = { name1 = "Irish acre", symbol = "Irish&nbsp;acres", utype = "area", scale = 6555.2385024, default = "ha", link = "Acre (Irish)", }, ["m2"] = { _name1 = "square metre", _name1_us= "square meter", _symbol = "m<sup>2</sup>", prefix_position= 8, utype = "area", scale = 1, prefixes = 2, default = "sqft", link = "Square metre", }, ["pondemaat"] = { name1 = "pondemaat", name2 = "pondemaat", symbol = "pond", utype = "area", scale = 3674.363358816, default = "m2", link = ":nl:pondemaat", }, ["pyeong"] = { name2 = "pyeong", symbol = "pyeong", usename = 1, utype = "area", scale = 3.3057851239669422, default = "m2", }, ["rai"] = { name2 = "rai", symbol = "rai", utype = "area", scale = 1600, default = "m2", link = "Rai (unit)", }, ["rood"] = { symbol = "rood", usename = 1, utype = "area", scale = 1011.7141056, default = "sqft m2", subdivs = { ["sqperch"] = { 40, default = "m2" } }, link = "Rood (unit)", }, ["sqfoot"] = { name1 = "square foot", name2 = "square foot", symbol = "sq&nbsp;ft", utype = "area", scale = 0.09290304, default = "m2", }, ["sqft"] = { name1 = "square foot", name2 = "square feet", symbol = "sq&nbsp;ft", utype = "area", scale = 0.09290304, default = "m2", }, ["sqin"] = { name1 = "square inch", name2 = "square inches", symbol = "sq&nbsp;in", utype = "area", scale = 0.00064516, default = "cm2", }, ["sqmi"] = { name1 = "square mile", symbol = "sq&nbsp;mi", utype = "area", scale = 2589988.110336, default = "km2", }, ["sqnmi"] = { name1 = "square nautical mile", symbol = "sq&nbsp;nmi", utype = "area", scale = 3429904, default = "km2 sqmi", link = "Nautical mile", }, ["sqperch"] = { name2 = "perches", symbol = "perch", usename = 1, utype = "area", scale = 25.29285264, default = "m2", link = "Rod (unit)#Area and volume", }, ["sqverst"] = { symbol = "square verst", usename = 1, utype = "area", scale = 1138062.24, default = "km2 sqmi", link = "Verst", }, ["sqyd"] = { name1 = "square yard", symbol = "sq&nbsp;yd", utype = "area", scale = 0.83612736, default = "m2", }, ["tsubo"] = { name2 = "tsubo", symbol = "tsubo", usename = 1, utype = "area", scale = 3.3057851239669422, default = "m2", link = "Japanese units of measurement#Area", }, ["acres"] = { target = "acre", }, ["are"] = { target = "a", }, ["decare"] = { target = "daa", }, ["foot2"] = { target = "sqfoot", }, ["ft2"] = { target = "sqft", }, ["in2"] = { target = "sqin", symbol = "in<sup>2</sup>", }, ["km²"] = { target = "km2", }, ["mi2"] = { target = "sqmi", }, ["million acre"] = { target = "e6acre", }, ["million acres"] = { target = "e6acre", }, ["million hectares"] = { target = "e6ha", }, ["m²"] = { target = "m2", }, ["nmi2"] = { target = "sqnmi", }, ["pond"] = { target = "pondemaat", }, ["sq arp"] = { target = "arpent", }, ["sqkm"] = { target = "km2", }, ["sqm"] = { target = "m2", }, ["square verst"] = { target = "sqverst", }, ["verst2"] = { target = "sqverst", }, ["yd2"] = { target = "sqyd", }, ["m2/ha"] = { name1 = "square metre per hectare", name1_us = "square meter per hectare", name2 = "square metres per hectare", name2_us = "square meters per hectare", symbol = "m<sup>2</sup>/ha", utype = "area per unit area", scale = 0.0001, default = "sqft/acre", link = "Basal area", }, ["sqft/acre"] = { name1 = "square foot per acre", name2 = "square feet per acre", symbol = "sq&nbsp;ft/acre", utype = "area per unit area", scale = 2.295684113865932e-5, default = "m2/ha", link = "Basal area", }, ["cent"] = { name1 = "cent", symbol = "¢", utype = "cent", scale = 1, default = "cent", link = "Cent (currency)", }, ["¢"] = { target = "cent", }, ["A.h"] = { name1 = "ampere hour", symbol = "A⋅h", utype = "charge", scale = 3600, default = "coulomb", }, ["coulomb"] = { _name1 = "coulomb", _symbol = "C", utype = "charge", scale = 1, prefixes = 1, default = "e", link = "Coulomb", }, ["e"] = { name1 = "elementary charge", symbol = "''e''", utype = "charge", scale = 1.602176487e-19, default = "coulomb", }, ["g-mol"] = { name1 = "gram-mole", symbol = "g&#8209;mol", utype = "chemical amount", scale = 1, default = "lbmol", link = "Mole (unit)", }, ["gmol"] = { name1 = "gram-mole", symbol = "gmol", utype = "chemical amount", scale = 1, default = "lbmol", link = "Mole (unit)", }, ["kmol"] = { name1 = "kilomole", symbol = "kmol", utype = "chemical amount", scale = 1000, default = "lbmol", link = "Mole (unit)", }, ["lb-mol"] = { name1 = "pound-mole", symbol = "lb&#8209;mol", utype = "chemical amount", scale = 453.59237, default = "mol", }, ["lbmol"] = { name1 = "pound-mole", symbol = "lbmol", utype = "chemical amount", scale = 453.59237, default = "mol", }, ["mol"] = { name1 = "mole", symbol = "mol", utype = "chemical amount", scale = 1, default = "lbmol", link = "Mole (unit)", }, ["kgCO2/L"] = { name1 = "kilogram per litre", name1_us = "kilogram per liter", name2 = "kilograms per litre", name2_us = "kilograms per liter", symbol = "kg(CO<sub>2</sub>)/L", utype = "co2 per unit volume", scale = 1000, default = "lbCO2/USgal", link = "Exhaust gas", }, ["lbCO2/USgal"] = { name1 = "pound per US gallon", name2 = "pounds per US gallon", symbol = "lbCO2/US&nbsp;gal", utype = "co2 per unit volume", scale = 119.82642731689663, default = "kgCO2/L", link = "Exhaust gas", }, ["oz/lb"] = { per = { "oz", "lb" }, utype = "concentration", default = "mg/kg", }, ["mg/kg"] = { per = { "mg", "kg" }, utype = "concentration", default = "oz/lb", }, ["g/dm3"] = { name1 = "gram per cubic decimetre", name1_us = "gram per cubic decimeter", name2 = "grams per cubic decimetre", name2_us = "grams per cubic decimeter", symbol = "g/dm<sup>3</sup>", utype = "density", scale = 1, default = "kg/m3", link = "Density", }, ["g/L"] = { name1 = "gram per litre", name1_us = "gram per liter", name2 = "grams per litre", name2_us = "grams per liter", symbol = "g/L", utype = "density", scale = 1, default = "lb/cuin", link = "Density", }, ["g/mL"] = { name1 = "gram per millilitre", name1_us = "gram per milliliter", name2 = "grams per millilitre", name2_us = "grams per milliliter", symbol = "g/mL", utype = "density", scale = 1000, default = "lb/cuin", link = "Density", }, ["g/ml"] = { name1 = "gram per millilitre", name1_us = "gram per milliliter", name2 = "grams per millilitre", name2_us = "grams per milliliter", symbol = "g/ml", utype = "density", scale = 1000, default = "lb/cuin", link = "Density", }, ["kg/dm3"] = { name1 = "kilogram per cubic decimetre", name1_us = "kilogram per cubic decimeter", name2 = "kilograms per cubic decimetre", name2_us = "kilograms per cubic decimeter", symbol = "kg/dm<sup>3</sup>", utype = "density", scale = 1000, default = "lb/cuft", link = "Density", }, ["kg/L"] = { name1 = "kilogram per litre", name1_us = "kilogram per liter", name2 = "kilograms per litre", name2_us = "kilograms per liter", symbol = "kg/L", utype = "density", scale = 1000, default = "lb/USgal", link = "Density", }, ["kg/l"] = { name1 = "kilogram per litre", name1_us = "kilogram per liter", name2 = "kilograms per litre", name2_us = "kilograms per liter", symbol = "kg/l", utype = "density", scale = 1000, default = "lb/USgal", link = "Density", }, ["kg/m3"] = { name1 = "kilogram per cubic metre", name1_us = "kilogram per cubic meter", name2 = "kilograms per cubic metre", name2_us = "kilograms per cubic meter", symbol = "kg/m<sup>3</sup>", utype = "density", scale = 1, default = "lb/cuyd", link = "Density", }, ["lb/cuft"] = { name1 = "pound per cubic foot", name2 = "pounds per cubic foot", symbol = "lb/cu&nbsp;ft", utype = "density", scale = 16.018463373960142, default = "g/cm3", link = "Density", }, ["lb/cuin"] = { name1 = "pound per cubic inch", name2 = "pounds per cubic inch", symbol = "lb/cu&nbsp;in", utype = "density", scale = 27679.904710203122, default = "g/cm3", link = "Density", }, ["lb/cuyd"] = { name1 = "pound per cubic yard", name2 = "pounds per cubic yard", symbol = "lb/cu&nbsp;yd", utype = "density", scale = 0.5932764212577829, default = "kg/m3", link = "Density", }, ["lb/impgal"] = { name1 = "pound per imperial gallon", name2 = "pounds per imperial gallon", symbol = "lb/imp&nbsp;gal", utype = "density", scale = 99.776372663101697, default = "kg/L", link = "Density", }, ["lb/in3"] = { name1 = "pound per cubic inch", name2 = "pounds per cubic inch", symbol = "lb/cu&thinsp;in", utype = "density", scale = 27679.904710203122, default = "g/cm3", link = "Density", }, ["lb/U.S.gal"] = { name1 = "pound per U.S. gallon", name2 = "pounds per U.S. gallon", symbol = "lb/U.S.&nbsp;gal", utype = "density", scale = 119.82642731689663, default = "kg/L", link = "Density", }, ["lb/USbu"] = { name1 = "pound per US bushel", name2 = "pounds per US bushel", symbol = "lb/US&nbsp;bu", utype = "density", scale = 12.871859780974471, default = "kg/m3", link = "Bushel", }, ["lb/USgal"] = { name1 = "pound per US gallon", name2 = "pounds per US gallon", symbol = "lb/US&nbsp;gal", utype = "density", scale = 119.82642731689663, default = "kg/L", link = "Density", }, ["lbm/cuin"] = { name1 = "pound mass per cubic inch", name2 = "pounds mass per cubic inch", symbol = "lbm/cu&thinsp;in", utype = "density", scale = 27679.904710203122, default = "g/cm3", link = "Density", }, ["mg/L"] = { name1 = "milligram per litre", name1_us = "milligram per liter", name2 = "milligrams per litre", name2_us = "milligrams per liter", symbol = "mg/L", utype = "density", scale = 0.001, default = "lb/cuin", link = "Density", }, ["oz/cuin"] = { name1 = "ounce per cubic inch", name2 = "ounces per cubic inch", symbol = "oz/cu&nbsp;in", utype = "density", scale = 1729.9940443876951, default = "g/cm3", link = "Density", }, ["g/cm3"] = { per = { "g", "cm3" }, utype = "density", default = "lb/cuin", }, ["g/m3"] = { per = { "g", "m3" }, utype = "density", default = "lb/cuyd", link = "Density", }, ["Mg/m3"] = { per = { "Mg", "m3" }, utype = "density", default = "lb/cuft", }, ["mg/l"] = { per = { "mg", "l" }, utype = "density", default = "oz/cuin", }, ["μg/dL"] = { per = { "μg", "dL" }, utype = "density", default = "lb/cuin", }, ["μg/l"] = { per = { "μg", "l" }, utype = "density", default = "oz/cuin", }, ["lb/ft3"] = { target = "lb/cuft", }, ["lb/yd3"] = { target = "lb/cuyd", }, ["lbm/in3"] = { target = "lbm/cuin", }, ["mcg/dL"] = { target = "μg/dL", }, ["oz/in3"] = { target = "oz/cuin", }, ["ug/dL"] = { target = "μg/dL", }, ["ug/l"] = { target = "μg/l", }, ["B.O.T.U."] = { name1 = "Board of Trade Unit", symbol = "B.O.T.U.", utype = "energy", scale = 3600000, default = "MJ", link = "Kilowatt-hour", }, ["bboe"] = { name1 = "barrel of oil equivalent", name2 = "barrels of oil equivalent", symbol = "bboe", utype = "energy", scale = 6117863200, default = "GJ", }, ["BOE"] = { name1 = "barrel of oil equivalent", name2 = "barrels of oil equivalent", symbol = "BOE", utype = "energy", scale = 6117863200, default = "GJ", }, ["BTU"] = { name1 = "British thermal unit", symbol = "BTU", utype = "energy", scale = 1055.05585262, default = "kJ", }, ["Btu"] = { name1 = "British thermal unit", symbol = "Btu", utype = "energy", scale = 1055.05585262, default = "kJ", }, ["BTU-39F"] = { name1 = "British thermal unit (39°F)", name2 = "British thermal units (39°F)", symbol = "BTU<sub>39°F</sub>", utype = "energy", scale = 1059.67, default = "kJ", link = "British thermal unit", }, ["Btu-39F"] = { name1 = "British thermal unit (39°F)", name2 = "British thermal units (39°F)", symbol = "Btu<sub>39°F</sub>", utype = "energy", scale = 1059.67, default = "kJ", link = "British thermal unit", }, ["BTU-59F"] = { name1 = "British thermal unit (59°F)", name2 = "British thermal units (59°F)", symbol = "BTU<sub>59°F</sub>", utype = "energy", scale = 1054.804, default = "kJ", link = "British thermal unit", }, ["Btu-59F"] = { name1 = "British thermal unit (59°F)", name2 = "British thermal units (59°F)", symbol = "Btu<sub>59°F</sub>", utype = "energy", scale = 1054.804, default = "kJ", link = "British thermal unit", }, ["BTU-60F"] = { name1 = "British thermal unit (60°F)", name2 = "British thermal units (60°F)", symbol = "BTU<sub>60°F</sub>", utype = "energy", scale = 1054.68, default = "kJ", link = "British thermal unit", }, ["Btu-60F"] = { name1 = "British thermal unit (60°F)", name2 = "British thermal units (60°F)", symbol = "Btu<sub>60°F</sub>", utype = "energy", scale = 1054.68, default = "kJ", link = "British thermal unit", }, ["BTU-63F"] = { name1 = "British thermal unit (63°F)", name2 = "British thermal units (63°F)", symbol = "BTU<sub>63°F</sub>", utype = "energy", scale = 1054.6, default = "kJ", link = "British thermal unit", }, ["Btu-63F"] = { name1 = "British thermal unit (63°F)", name2 = "British thermal units (63°F)", symbol = "Btu<sub>63°F</sub>", utype = "energy", scale = 1054.6, default = "kJ", link = "British thermal unit", }, ["BTU-ISO"] = { name1 = "British thermal unit (ISO)", name2 = "British thermal units (ISO)", symbol = "BTU<sub>ISO</sub>", utype = "energy", scale = 1055.056, default = "kJ", link = "British thermal unit", }, ["Btu-ISO"] = { target = "BTU-ISO", }, ["BTU-IT"] = { name1 = "British thermal unit (IT)", name2 = "British thermal units (IT)", symbol = "BTU<sub>IT</sub>", utype = "energy", scale = 1055.05585262, default = "kJ", link = "British thermal unit", }, ["Btu-IT"] = { name1 = "British thermal unit (IT)", name2 = "British thermal units (IT)", symbol = "Btu<sub>IT</sub>", utype = "energy", scale = 1055.05585262, default = "kJ", link = "British thermal unit", }, ["BTU-mean"] = { name1 = "British thermal unit (mean)", name2 = "British thermal units (mean)", symbol = "BTU<sub>mean</sub>", utype = "energy", scale = 1055.87, default = "kJ", link = "British thermal unit", }, ["Btu-mean"] = { name1 = "British thermal unit (mean)", name2 = "British thermal units (mean)", symbol = "Btu<sub>mean</sub>", utype = "energy", scale = 1055.87, default = "kJ", link = "British thermal unit", }, ["BTU-th"] = { name1 = "British thermal unit (thermochemical)", name2 = "British thermal units (thermochemical)", symbol = "BTU<sub>th</sub>", utype = "energy", scale = 1054.35026444, default = "kJ", link = "British thermal unit", }, ["Btu-th"] = { name1 = "British thermal unit (thermochemical)", name2 = "British thermal units (thermochemical)", symbol = "Btu<sub>th</sub>", utype = "energy", scale = 1054.35026444, default = "kJ", link = "British thermal unit", }, ["Cal"] = { name1 = "calorie", symbol = "Cal", utype = "energy", scale = 4184, default = "kJ", }, ["cal"] = { name1 = "calorie", symbol = "cal", utype = "energy", scale = 4.184, default = "J", }, ["Cal-15"] = { name1 = "Calorie (15°C)", name2 = "Calories (15°C)", symbol = "Cal<sub>15</sub>", utype = "energy", scale = 4185.8, default = "kJ", link = "Calorie", }, ["cal-15"] = { name1 = "calorie (15°C)", name2 = "calories (15°C)", symbol = "cal<sub>15</sub>", utype = "energy", scale = 4.1858, default = "J", link = "Calorie", }, ["Cal-IT"] = { name1 = "Calorie (International Steam Table)", name2 = "Calories (International Steam Table)", symbol = "Cal<sub>IT</sub>", utype = "energy", scale = 4186.8, default = "kJ", link = "Calorie", }, ["cal-IT"] = { name1 = "calorie (International Steam Table)", name2 = "calories (International Steam Table)", symbol = "cal<sub>IT</sub>", utype = "energy", scale = 4.1868, default = "J", link = "Calorie", }, ["Cal-th"] = { name1 = "Calorie (thermochemical)", name2 = "Calories (thermochemical)", symbol = "Cal<sub>th</sub>", utype = "energy", scale = 4184, default = "kJ", link = "Calorie", }, ["cal-th"] = { name1 = "calorie (thermochemical)", name2 = "calories (thermochemical)", symbol = "cal<sub>th</sub>", utype = "energy", scale = 4.184, default = "J", link = "Calorie", }, ["CHU-IT"] = { name1 = "Celsius heat unit (International Table)", name2 = "Celsius heat units (International Table)", symbol = "CHU<sub>IT</sub>", utype = "energy", scale = 1899.100534716, default = "kJ", link = "Conversion of units#Energy", }, ["cufootnaturalgas"] = { name1 = "cubic foot of natural gas", name2 = "cubic foot of natural gas", symbol = "cuftnaturalgas", usename = 1, utype = "energy", scale = 1055055.85262, default = "MJ", link = "Conversion of units#Energy", }, ["cuftnaturalgas"] = { name1 = "cubic foot of natural gas", name2 = "cubic feet of natural gas", symbol = "cuftnaturalgas", usename = 1, utype = "energy", scale = 1055055.85262, default = "MJ", link = "Conversion of units#Energy", }, ["Eh"] = { name1 = "Hartree", symbol = "''E''<sub>h</sub>", utype = "energy", scale = 4.35974417e-18, default = "eV", }, ["erg"] = { symbol = "erg", utype = "energy", scale = 0.0000001, default = "μJ", }, ["eV"] = { name1 = "electronvolt", symbol = "eV", utype = "energy", scale = 1.602176487e-19, default = "aJ", }, ["feV"] = { name1 = "femtoelectronvolt", symbol = "feV", utype = "energy", scale = 1.602176487e-34, default = "yJ", link = "Electronvolt", }, ["foe"] = { symbol = "foe", utype = "energy", scale = 1e44, default = "YJ", link = "Foe (unit)", }, ["ftlb"] = { name1 = "foot-pound", symbol = "ft⋅lb", utype = "energy", alttype = "torque", scale = 1.3558179483314004, default = "J", link = "Foot-pound (energy)", }, ["ftlb-f"] = { name1 = "foot-pound force", name2 = "foot-pounds force", symbol = "ft⋅lb<sub>f</sub>", utype = "energy", alttype = "torque", scale = 1.3558179483314004, default = "J", link = "Foot-pound (energy)", }, ["ftlbf"] = { name1 = "foot-pound force", name2 = "foot-pounds force", symbol = "ft⋅lbf", utype = "energy", alttype = "torque", scale = 1.3558179483314004, default = "J", link = "Foot-pound (energy)", }, ["ftpdl"] = { name1 = "foot-poundal", symbol = "ft⋅pdl", utype = "energy", scale = 0.0421401100938048, default = "J", }, ["GeV"] = { name1 = "gigaelectronvolt", symbol = "GeV", utype = "energy", scale = 1.602176487e-10, default = "nJ", link = "Electronvolt", }, ["gTNT"] = { name2 = "grams of TNT", symbol = "gram of TNT", usename = 1, utype = "energy", scale = 4184, default = "kJ", link = "TNT equivalent", }, ["Gtoe"] = { name1 = "gigatonne of oil equivalent", name2 = "gigatonnes of oil equivalent", symbol = "Gtoe", utype = "energy", scale = 4.1868e19, default = "EJ", link = "Tonne of oil equivalent", }, ["GtonTNT"] = { name2 = "gigatons of TNT", symbol = "gigaton of TNT", usename = 1, utype = "energy", scale = 4.184e18, default = "EJ", link = "TNT equivalent", }, ["GtTNT"] = { name2 = "gigatonnes of TNT", symbol = "gigatonne of TNT", usename = 1, utype = "energy", scale = 4.184e18, default = "EJ", link = "TNT equivalent", }, ["GW.h"] = { name1 = "gigawatt-hour", symbol = "GW⋅h", utype = "energy", scale = 3.6e12, default = "TJ", link = "Kilowatt-hour", }, ["GWh"] = { name1 = "gigawatt-hour", symbol = "GWh", utype = "energy", scale = 3.6e12, default = "TJ", link = "Kilowatt-hour", }, ["hph"] = { name1 = "horsepower-hour", symbol = "hp⋅h", utype = "energy", scale = 2684519.537696172792, default = "kWh", link = "Horsepower", }, ["inlb"] = { name1 = "inch-pound", symbol = "in⋅lb", utype = "energy", alttype = "torque", scale = 0.1129848290276167, default = "mJ", link = "Foot-pound (energy)", }, ["inlb-f"] = { name1 = "inch-pound force", name2 = "inch-pounds force", symbol = "in⋅lb<sub>f</sub>", utype = "energy", alttype = "torque", scale = 0.1129848290276167, default = "mJ", link = "Foot-pound (energy)", }, ["inlbf"] = { name1 = "inch-pound force", name2 = "inch-pounds force", symbol = "in⋅lbf", utype = "energy", alttype = "torque", scale = 0.1129848290276167, default = "mJ", link = "Foot-pound (energy)", }, ["inoz-f"] = { name1 = "inch-ounce force", name2 = "inch-ounces force", symbol = "in⋅oz<sub>f</sub>", utype = "energy", alttype = "torque", scale = 0.00706155181422604375, default = "mJ", link = "Foot-pound (energy)", }, ["inozf"] = { name1 = "inch-ounce force", name2 = "inch-ounces force", symbol = "in⋅ozf", utype = "energy", alttype = "torque", scale = 0.00706155181422604375, default = "mJ", link = "Foot-pound (energy)", }, ["J"] = { _name1 = "joule", _symbol = "J", utype = "energy", scale = 1, prefixes = 1, default = "cal", link = "Joule", }, ["kBOE"] = { name1 = "kilo barrel of oil equivalent", name2 = "kilo barrels of oil equivalent", symbol = "kBOE", utype = "energy", scale = 6.1178632e12, default = "TJ", link = "Barrel of oil equivalent", }, ["kcal"] = { name1 = "kilocalorie", symbol = "kcal", utype = "energy", scale = 4184, default = "kJ", link = "Calorie", }, ["kcal-15"] = { name1 = "kilocalorie (15°C)", name2 = "kilocalories (15°C)", symbol = "kcal<sub>15</sub>", utype = "energy", scale = 4185.8, default = "kJ", link = "Calorie", }, ["kcal-IT"] = { name1 = "kilocalorie (International Steam Table)", name2 = "kilocalories (International Steam Table)", symbol = "kcal<sub>IT</sub>", utype = "energy", scale = 4186.8, default = "kJ", link = "Calorie", }, ["kcal-th"] = { name1 = "kilocalorie (thermochemical)", name2 = "kilocalories (thermochemical)", symbol = "kcal<sub>th</sub>", utype = "energy", scale = 4184, default = "kJ", link = "Calorie", }, ["kerg"] = { name1 = "kiloerg", symbol = "kerg", utype = "energy", scale = 0.0001, default = "mJ", link = "Erg", }, ["keV"] = { name1 = "kiloelectronvolt", symbol = "keV", utype = "energy", scale = 1.602176487e-16, default = "fJ", link = "Electronvolt", }, ["kgTNT"] = { name2 = "kilograms of TNT", symbol = "kilogram of TNT", usename = 1, utype = "energy", scale = 4184000, default = "MJ", link = "TNT equivalent", }, ["kt(TNT)"] = { name1 = "kilotonne", name1_us = "kiloton", symbol = "kt", utype = "energy", scale = 4.184e12, default = "TJ", link = "TNT equivalent", }, ["ktoe"] = { name1 = "kilotonne of oil equivalent", name2 = "kilotonnes of oil equivalent", symbol = "ktoe", utype = "energy", scale = 4.1868e13, default = "TJ", link = "Tonne of oil equivalent", }, ["ktonTNT"] = { name1 = "kiloton of TNT", name2 = "kilotons of TNT", symbol = "kt", utype = "energy", scale = 4.184e12, default = "TJ", link = "TNT equivalent", }, ["ktTNT"] = { name2 = "kilotonnes of TNT", symbol = "kilotonne of TNT", usename = 1, utype = "energy", scale = 4.184e12, default = "TJ", link = "TNT equivalent", }, ["kW.h"] = { name1 = "kilowatt-hour", symbol = "kW⋅h", utype = "energy", scale = 3600000, default = "MJ", }, ["kWh"] = { name1 = "kilowatt-hour", symbol = "kWh", utype = "energy", scale = 3600000, default = "MJ", }, ["Mcal"] = { name1 = "megacalorie", symbol = "Mcal", utype = "energy", scale = 4184000, default = "MJ", link = "Calorie", }, ["mcal"] = { name1 = "millicalorie", symbol = "mcal", utype = "energy", scale = 0.004184, default = "mJ", link = "Calorie", }, ["Mcal-15"] = { name1 = "megacalorie (15°C)", name2 = "megacalories (15°C)", symbol = "Mcal<sub>15</sub>", utype = "energy", scale = 4185800, default = "MJ", link = "Calorie", }, ["mcal-15"] = { name1 = "millicalorie (15°C)", name2 = "millicalories (15°C)", symbol = "mcal<sub>15</sub>", utype = "energy", scale = 0.0041858, default = "mJ", link = "Calorie", }, ["Mcal-IT"] = { name1 = "megacalorie (International Steam Table)", name2 = "megacalories (International Steam Table)", symbol = "Mcal<sub>IT</sub>", utype = "energy", scale = 4186800, default = "MJ", link = "Calorie", }, ["mcal-IT"] = { name1 = "millicalorie (International Steam Table)", name2 = "millicalories (International Steam Table)", symbol = "mcal<sub>IT</sub>", utype = "energy", scale = 0.0041868, default = "mJ", link = "Calorie", }, ["Mcal-th"] = { name1 = "megacalorie (thermochemical)", name2 = "megacalories (thermochemical)", symbol = "Mcal<sub>th</sub>", utype = "energy", scale = 4184000, default = "MJ", link = "Calorie", }, ["mcal-th"] = { name1 = "millicalorie (thermochemical)", name2 = "millicalories (thermochemical)", symbol = "mcal<sub>th</sub>", utype = "energy", scale = 0.004184, default = "mJ", link = "Calorie", }, ["Merg"] = { name1 = "megaerg", symbol = "Merg", utype = "energy", scale = 0.1, default = "J", link = "Erg", }, ["merg"] = { name1 = "millierg", symbol = "merg", utype = "energy", scale = 0.0000000001, default = "μJ", link = "Erg", }, ["MeV"] = { name1 = "megaelectronvolt", symbol = "MeV", utype = "energy", scale = 1.602176487e-13, default = "pJ", link = "Electronvolt", }, ["meV"] = { name1 = "millielectronvolt", symbol = "meV", utype = "energy", scale = 1.602176487e-22, default = "zJ", link = "Electronvolt", }, ["MMBtu"] = { name1 = "million British thermal units", name2 = "million British thermal units", symbol = "MMBtu", utype = "energy", scale = 1055055852.62, default = "GJ", link = "British thermal unit", }, ["Mt(TNT)"] = { name1 = "megatonne", name1_us = "megaton", symbol = "Mt", utype = "energy", scale = 4.184e15, default = "PJ", link = "TNT equivalent", }, ["Mtoe"] = { name1 = "megatonne of oil equivalent", name2 = "megatonnes of oil equivalent", symbol = "Mtoe", utype = "energy", scale = 4.1868e16, default = "PJ", link = "Tonne of oil equivalent", }, ["MtonTNT"] = { name1 = "megaton of TNT", name2 = "megatons of TNT", symbol = "Mt", utype = "energy", scale = 4.184e15, default = "PJ", link = "TNT equivalent", }, ["mtonTNT"] = { name2 = "millitons of TNT", symbol = "milliton of TNT", usename = 1, utype = "energy", scale = 4184000, default = "MJ", link = "TNT equivalent", }, ["MtTNT"] = { name2 = "megatonnes of TNT", symbol = "megatonne of TNT", usename = 1, utype = "energy", scale = 4.184e15, default = "PJ", link = "TNT equivalent", }, ["mtTNT"] = { name2 = "millitonnes of TNT", symbol = "millitonne of TNT", usename = 1, utype = "energy", scale = 4184000, default = "MJ", link = "TNT equivalent", }, ["MW.h"] = { name1 = "megawatt-hour", symbol = "MW⋅h", utype = "energy", scale = 3600000000, default = "GJ", link = "Kilowatt-hour", }, ["mW.h"] = { name1 = "milliwatt-hour", symbol = "mW⋅h", utype = "energy", scale = 3.6, default = "J", link = "Kilowatt-hour", }, ["MWh"] = { name1 = "megawatt-hour", symbol = "MWh", utype = "energy", scale = 3600000000, default = "GJ", link = "Kilowatt-hour", }, ["mWh"] = { name1 = "milliwatt-hour", symbol = "mWh", utype = "energy", scale = 3.6, default = "J", link = "Kilowatt-hour", }, ["neV"] = { name1 = "nanoelectronvolt", symbol = "neV", utype = "energy", scale = 1.602176487e-28, default = "yJ", link = "Electronvolt", }, ["PeV"] = { name1 = "petaelectronvolt", symbol = "PeV", utype = "energy", scale = 0.0001602176487, default = "mJ", link = "Electronvolt", }, ["peV"] = { name1 = "picoelectronvolt", symbol = "peV", utype = "energy", scale = 1.602176487e-31, default = "yJ", link = "Electronvolt", }, ["PSh"] = { name1 = "Pferdestärkenstunde", symbol = "PSh", utype = "energy", scale = 2647795.5, default = "kWh", }, ["quad"] = { name1 = "quadrillion British thermal units", name2 = "quadrillion British thermal units", symbol = "quad", utype = "energy", scale = 1.054804e18, default = "EJ", link = "Quad (unit)", }, ["Ry"] = { name1 = "rydberg", symbol = "Ry", utype = "energy", scale = 2.1798741e-18, default = "eV", link = "Rydberg constant", }, ["scf"] = { name1 = "standard cubic foot", name2 = "standard cubic feet", symbol = "scf", utype = "energy", scale = 2869.2044809344, default = "kJ", }, ["scfoot"] = { name1 = "standard cubic foot", name2 = "standard cubic foot", symbol = "scf", utype = "energy", scale = 2869.2044809344, default = "kJ", }, ["t(TNT)"] = { name1 = "tonne", name1_us = "ton", symbol = "t", utype = "energy", scale = 4184000000, default = "GJ", link = "TNT equivalent", }, ["TeV"] = { name1 = "teraelectronvolt", symbol = "TeV", utype = "energy", scale = 1.602176487e-7, default = "μJ", link = "Electronvolt", }, ["th"] = { name1 = "thermie", symbol = "th", utype = "energy", scale = 4186800, default = "MJ", link = "Conversion of units#Energy", }, ["thm-EC"] = { name1 = "therm (EC)", name2 = "therms (EC)", symbol = "thm (EC)", utype = "energy", scale = 105506000, default = "MJ", link = "Therm", }, ["thm-UK"] = { name1 = "therm (UK)", name2 = "therms (UK)", symbol = "thm (UK)", utype = "energy", scale = 105505585.257348, default = "MJ", link = "Therm", }, ["thm-US"] = { name1 = "therm (US)", name1_us = "therm (U.S.)", name2 = "therms (US)", name2_us = "therms (U.S.)", symbol = "thm (US)", sym_us = "thm (U.S.)", utype = "energy", scale = 105480400, default = "MJ", link = "Therm", }, ["toe"] = { name1 = "tonne of oil equivalent", name2 = "tonnes of oil equivalent", symbol = "toe", utype = "energy", scale = 41868000000, default = "GJ", }, ["tonTNT"] = { name2 = "tons of TNT", symbol = "ton of TNT", usename = 1, utype = "energy", scale = 4184000000, default = "GJ", link = "TNT equivalent", }, ["tTNT"] = { name2 = "tonnes of TNT", symbol = "tonne of TNT", usename = 1, utype = "energy", scale = 4184000000, default = "GJ", link = "TNT equivalent", }, ["TtonTNT"] = { name2 = "teratons of TNT", symbol = "teraton of TNT", usename = 1, utype = "energy", scale = 4.184e21, default = "ZJ", link = "TNT equivalent", }, ["TtTNT"] = { name2 = "teratonnes of TNT", symbol = "teratonne of TNT", usename = 1, utype = "energy", scale = 4.184e21, default = "ZJ", link = "TNT equivalent", }, ["TW.h"] = { name1 = "terawatt-hour", symbol = "TW⋅h", utype = "energy", scale = 3.6e15, default = "PJ", link = "Kilowatt-hour", }, ["TWh"] = { name1 = "terawatt-hour", symbol = "TWh", utype = "energy", scale = 3.6e15, default = "PJ", link = "Kilowatt-hour", }, ["W.h"] = { name1 = "watt-hour", symbol = "W⋅h", utype = "energy", scale = 3600, default = "kJ", link = "Kilowatt-hour", }, ["Wh"] = { name1 = "watt-hour", symbol = "Wh", utype = "energy", scale = 3600, default = "kJ", link = "Kilowatt-hour", }, ["μerg"] = { name1 = "microerg", symbol = "μerg", utype = "energy", scale = 1e-13, default = "nJ", link = "Erg", }, ["μeV"] = { name1 = "microelectronvolt", symbol = "μeV", utype = "energy", scale = 1.602176487e-25, default = "yJ", link = "Electronvolt", }, ["μW.h"] = { name1 = "microwatt-hour", symbol = "μW⋅h", utype = "energy", scale = 0.0036, default = "mJ", link = "Kilowatt-hour", }, ["μWh"] = { name1 = "microwatt-hour", symbol = "μWh", utype = "energy", scale = 0.0036, default = "mJ", link = "Kilowatt-hour", }, ["-kW.h"] = { target = "kW.h", link = "Kilowatt hour", }, ["btu"] = { target = "BTU", }, ["Calorie"] = { target = "Cal", }, ["ft.lbf"] = { target = "ftlbf", }, ["ft·lbf"] = { target = "ftlbf", }, ["g-cal-15"] = { target = "cal-15", }, ["g-cal-IT"] = { target = "cal-IT", }, ["g-cal-th"] = { target = "cal-th", }, ["g-kcal-15"] = { target = "kcal-15", }, ["g-kcal-IT"] = { target = "kcal-IT", }, ["g-kcal-th"] = { target = "kcal-th", }, ["g-Mcal-15"] = { target = "Mcal-15", }, ["g-mcal-15"] = { target = "mcal-15", }, ["g-Mcal-IT"] = { target = "Mcal-IT", }, ["g-mcal-IT"] = { target = "mcal-IT", }, ["g-Mcal-th"] = { target = "Mcal-th", }, ["g-mcal-th"] = { target = "mcal-th", }, ["GW-h"] = { target = "GW.h", }, ["GW·h"] = { target = "GW.h", }, ["Hartree"] = { target = "Eh", }, ["hp.h"] = { target = "hph", }, ["in.lb-f"] = { target = "inlb-f", }, ["in.lbf"] = { target = "inlbf", }, ["in.oz-f"] = { target = "inoz-f", }, ["in.ozf"] = { target = "inozf", }, ["kbboe"] = { target = "kBOE", symbol = "kbboe", }, ["kg-cal-15"] = { target = "Cal-15", }, ["kg-cal-IT"] = { target = "Cal-IT", }, ["kg-cal-th"] = { target = "Cal-th", }, ["kW-h"] = { target = "kW.h", }, ["kW·h"] = { target = "kW.h", }, ["MW-h"] = { target = "MW.h", }, ["mW-h"] = { target = "mW.h", }, ["MW·h"] = { target = "MW.h", }, ["TW-h"] = { target = "TW.h", }, ["uerg"] = { target = "μerg", }, ["ueV"] = { target = "μeV", }, ["uW-h"] = { target = "μW.h", }, ["uW.h"] = { target = "μW.h", }, ["uWh"] = { target = "μWh", }, ["W-h"] = { target = "W.h", }, ["eVpar"] = { _name1 = "electronvolt", _symbol = "eV", utype = "energy per chemical amount", scale = 96485.329522144166, prefixes = 1, default = "kcal/mol", link = "Electronvolt", }, ["kcal/mol"] = { per = { "kcal", "mol" }, utype = "energy per chemical amount", default = "kJ/mol", link = "Kilocalorie per mole", }, ["kJ/mol"] = { per = { "kJ", "mol" }, utype = "energy per chemical amount", default = "kcal/mol", link = "Joule per mole", }, ["kWh/100 km"] = { name1 = "kilowatt-hour per 100 kilometres", name1_us = "kilowatt-hour per 100 kilometers", name2 = "kilowatt-hours per 100 kilometres", name2_us = "kilowatt-hours per 100 kilometers", symbol = "kW⋅h/100&nbsp;km", utype = "energy per unit length", scale = 36, default = "MJ/km kWh/mi", link = "Kilowatt-hour", }, ["kWh/100 mi"] = { name1 = "kilowatt-hour per 100 miles", name2 = "kilowatt-hours per 100 miles", symbol = "kW⋅h/100&nbsp;mi", utype = "energy per unit length", scale = 22.3694, default = "mpge", link = "Miles per gallon gasoline equivalent", }, ["MJ/100 km"] = { name1 = "megajoule per 100 kilometres", name1_us = "megajoule per 100 kilometers", name2 = "megajoules per 100 kilometres", name2_us = "megajoules per 100 kilometers", symbol = "MJ/100&nbsp;km", utype = "energy per unit length", scale = 10, default = "BTU/mi", link = "British thermal unit", }, ["mpge"] = { name1 = "mile per gallon gasoline equivalent", name2 = "miles per gallon gasoline equivalent", symbol = "mpg&#8209;e", utype = "energy per unit length", scale = 13e-6, invert = -1, iscomplex= true, default = "kWh/100 mi", link = "Miles per gallon gasoline equivalent", }, ["BTU/mi"] = { per = { "BTU", "mi" }, utype = "energy per unit length", default = "v > 1525 ! M ! k ! J/km", }, ["kJ/km"] = { per = { "kJ", "km" }, utype = "energy per unit length", default = "BTU/mi", }, ["kWh/km"] = { per = { "-kW.h", "km" }, utype = "energy per unit length", default = "MJ/km kWh/mi", }, ["kWh/mi"] = { per = { "-kW.h", "mi" }, utype = "energy per unit length", default = "kWh/km MJ/km", }, ["MJ/km"] = { per = { "MJ", "km" }, utype = "energy per unit length", default = "BTU/mi", }, ["mpg-e"] = { target = "mpge", }, ["BTU/lb"] = { name1 = "British thermal unit per pound", name2 = "British thermal units per pound", symbol = "BTU/lb", utype = "energy per unit mass", scale = 429.92261414790346, default = "kJ/kg", link = "British thermal unit", }, ["cal/g"] = { name1 = "calorie per gram", name2 = "calories per gram", symbol = "cal/g", utype = "energy per unit mass", scale = 4184, default = "J/g", }, ["GJ/kg"] = { name1 = "gigajoule per kilogram", name2 = "gigajoules per kilogram", symbol = "GJ/kg", utype = "energy per unit mass", scale = 1e9, default = "ktTNT/t", link = "Specific energy", }, ["J/g"] = { name1 = "joule per gram", name2 = "joules per gram", symbol = "J/g", utype = "energy per unit mass", scale = 1000, default = "kcal/g", link = "Specific energy", }, ["kcal/g"] = { name1 = "kilocalorie per gram", name2 = "kilocalories per gram", symbol = "kcal/g", utype = "energy per unit mass", scale = 4184000, default = "kJ/g", }, ["kJ/g"] = { name1 = "kilojoule per gram", name2 = "kilojoules per gram", symbol = "kJ/g", utype = "energy per unit mass", scale = 1000000, default = "kcal/g", link = "Specific energy", }, ["kJ/kg"] = { name1 = "kilojoule per kilogram", name2 = "kilojoules per kilogram", symbol = "kJ/kg", utype = "energy per unit mass", scale = 1000, default = "BTU/lb", link = "Specific energy", }, ["ktonTNT/MT"] = { name2 = "kilotons of TNT per metric ton", symbol = "kiloton of TNT per metric ton", usename = 1, utype = "energy per unit mass", scale = 4184000000, default = "GJ/kg", link = "TNT equivalent", }, ["ktTNT/t"] = { name2 = "kilotonnes of TNT per tonne", symbol = "kilotonne of TNT per tonne", usename = 1, utype = "energy per unit mass", scale = 4184000000, default = "GJ/kg", link = "TNT equivalent", }, ["MtonTNT/MT"] = { name2 = "megatons of TNT per metric ton", symbol = "megaton of TNT per metric ton", usename = 1, utype = "energy per unit mass", scale = 4.184e12, default = "TJ/kg", link = "TNT equivalent", }, ["MtTNT/MT"] = { name2 = "megatonnes of TNT per tonne", symbol = "megatonne of TNT per tonne", usename = 1, utype = "energy per unit mass", scale = 4.184e12, default = "TJ/kg", link = "TNT equivalent", }, ["TJ/kg"] = { name1 = "terajoule per kilogram", name2 = "terajoules per kilogram", symbol = "TJ/kg", utype = "energy per unit mass", scale = 1e12, default = "MtTNT/MT", link = "Specific energy", }, ["Cal/g"] = { per = { "Cal", "g" }, utype = "energy per unit mass", default = "kJ/g", }, ["BTU/cuft"] = { per = { "BTU", "cuft" }, utype = "energy per unit volume", default = "kJ/L", }, ["Cal/12USoz(mL)serve"] = { per = { "Cal", "-12USoz(mL)serve" }, utype = "energy per unit volume", default = "kJ/L", }, ["Cal/12USoz(ml)serve"] = { per = { "Cal", "-12USoz(ml)serve" }, utype = "energy per unit volume", default = "kJ/l", }, ["Cal/12USozserve"] = { per = { "Cal", "-12USozserve" }, utype = "energy per unit volume", default = "kJ/L", }, ["Cal/USoz"] = { per = { "Cal", "USoz" }, utype = "energy per unit volume", default = "kJ/ml", }, ["kJ/L"] = { per = { "kJ", "L" }, utype = "energy per unit volume", default = "BTU/cuft", }, ["kJ/l"] = { per = { "kJ", "l" }, utype = "energy per unit volume", default = "BTU/cuft", }, ["kJ/ml"] = { per = { "kJ", "ml" }, utype = "energy per unit volume", default = "Cal/USoz", }, ["MJ/m3"] = { per = { "MJ", "m3" }, utype = "energy per unit volume", default = "BTU/cuft", }, ["Sv"] = { _name1 = "sievert", _symbol = "Sv", utype = "equivalent radiation dose", scale = 1, prefixes = 1, default = "rem", link = "Sievert", }, ["rem"] = { _name1 = "rem", _symbol = "rem", utype = "equivalent radiation dose", scale = 0.01, prefixes = 1, default = "Sv", link = "Roentgen equivalent man", }, ["g/km"] = { name1 = "gram per kilometre", name1_us = "gram per kilometer", name2 = "grams per kilometre", name2_us = "grams per kilometer", symbol = "g/km", utype = "exhaust emission", scale = 1e-6, default = "oz/mi", link = "Exhaust gas", }, ["g/mi"] = { name1 = "gram per mile", name2 = "grams per mile", symbol = "g/mi", utype = "exhaust emission", scale = 6.2137119223733397e-7, default = "g/km", link = "Exhaust gas", }, ["gCO2/km"] = { name1 = "gram of CO<sub>2</sub> per kilometre", name1_us = "gram of CO<sub>2</sub> per kilometer", name2 = "grams of CO<sub>2</sub> per kilometre", name2_us = "grams of CO<sub>2</sub> per kilometer", symbol = "g(CO<sub>2</sub>)/km", utype = "exhaust emission", scale = 1e-6, default = "ozCO2/mi", link = "Exhaust gas", }, ["gCO2/mi"] = { name1 = "gram of CO<sub>2</sub> per mile", name2 = "grams of CO<sub>2</sub> per mile", symbol = "g(CO<sub>2</sub>)/mi", utype = "exhaust emission", scale = 6.2137119223733397e-7, default = "gCO2/km", link = "Exhaust gas", }, ["kg/km"] = { name1 = "kilogram per kilometre", name1_us = "kilogram per kilometer", name2 = "kilograms per kilometre", name2_us = "kilograms per kilometer", symbol = "kg/km", utype = "exhaust emission", scale = 0.001, default = "lb/mi", link = "Exhaust gas", }, ["kgCO2/km"] = { name1 = "kilogram of CO<sub>2</sub> per kilometre", name1_us = "kilogram of CO<sub>2</sub> per kilometer", name2 = "kilograms of CO<sub>2</sub> per kilometre", name2_us = "kilograms of CO<sub>2</sub> per kilometer", symbol = "kg(CO<sub>2</sub>)/km", utype = "exhaust emission", scale = 0.001, default = "lbCO2/mi", link = "Exhaust gas", }, ["lb/mi"] = { name1 = "pound per mile", name2 = "pounds per mile", symbol = "lb/mi", utype = "exhaust emission", scale = 0.00028184923173665794, default = "kg/km", link = "Exhaust gas", }, ["lbCO2/mi"] = { name1 = "pound of CO<sub>2</sub> per mile", name2 = "pounds of CO<sub>2</sub> per mile", symbol = "lb(CO<sub>2</sub>)/mi", utype = "exhaust emission", scale = 0.00028184923173665794, default = "kgCO2/km", link = "Exhaust gas", }, ["oz/mi"] = { name1 = "ounce per mile", name2 = "ounces per mile", symbol = "oz/mi", utype = "exhaust emission", scale = 1.7615576983541121e-5, default = "g/km", link = "Exhaust gas", }, ["ozCO2/mi"] = { name1 = "ounce of CO<sub>2</sub> per mile", name2 = "ounces of CO<sub>2</sub> per mile", symbol = "oz(CO<sub>2</sub>)/mi", utype = "exhaust emission", scale = 1.7615576983541121e-5, default = "gCO2/km", link = "Exhaust gas", }, ["cuft/a"] = { name1 = "cubic foot per annum", name2 = "cubic feet per annum", symbol = "cu&nbsp;ft/a", utype = "flow", scale = 8.9730672142368242e-10, default = "m3/a", link = "Cubic foot per second", }, ["cuft/d"] = { name1 = "cubic foot per day", name2 = "cubic feet per day", symbol = "cu&nbsp;ft/d", utype = "flow", scale = 3.2774128000000003e-7, default = "m3/d", link = "Cubic foot per second", }, ["cuft/h"] = { name1 = "cubic foot per hour", name2 = "cubic feet per hour", symbol = "cu&nbsp;ft/h", utype = "flow", scale = 7.8657907200000004e-6, default = "m3/h", link = "Cubic foot per second", }, ["cuft/min"] = { name1 = "cubic foot per minute", name2 = "cubic feet per minute", symbol = "cu&nbsp;ft/min", utype = "flow", scale = 0.00047194744319999999, default = "m3/min", }, ["cuft/s"] = { name1 = "cubic foot per second", name2 = "cubic feet per second", symbol = "cu&nbsp;ft/s", utype = "flow", scale = 28316846592e-12, default = "m3/s", }, ["cumi/a"] = { name1 = "cubic mile per annum", name2 = "cubic miles per annum", symbol = "cu&nbsp;mi/a", utype = "flow", scale = 132.08171170940057, default = "km3/a", link = "Cubic foot per second", }, ["cuyd/h"] = { name1 = "cubic yard per hour", name2 = "cubic yards per hour", symbol = "cuyd/h", utype = "flow", scale = 0.00021237634944000001, default = "m3/h", link = "Cubic foot per second", }, ["cuyd/s"] = { name1 = "cubic yard per second", name2 = "cubic yards per second", symbol = "cu&nbsp;yd/s", utype = "flow", scale = 0.76455485798400002, default = "m3/s", }, ["Goilbbl/a"] = { name1 = "billion barrels per year", name2 = "billion barrels per year", symbol = "Gbbl/a", utype = "flow", scale = 5.0380033629933836, default = "v * 1.58987294928 < 10 ! e6 ! e9 ! m3/a", link = "Barrel per day", }, ["impgal/h"] = { name1 = "imperial gallon per hour", name2 = "imperial gallons per hour", symbol = "imp&nbsp;gal/h", utype = "flow", scale = 1.2628027777777779e-6, default = "m3/h", link = "Gallon", }, ["impgal/min"] = { name1 = "imperial gallon per minute", name2 = "imperial gallons per minute", symbol = "imp gal/min", utype = "flow", scale = 7.5768166666666671e-5, default = "m3/s", link = "Gallon", }, ["impgal/s"] = { name1 = "imperial gallon per second", name2 = "imperial gallons per second", symbol = "impgal/s", utype = "flow", scale = 0.00454609, default = "m3/s", link = "Imperial gallons per second", }, ["km3/a"] = { name1 = "cubic kilometre per annum", name1_us = "cubic kilometer per annum", name2 = "cubic kilometres per annum", name2_us = "cubic kilometers per annum", symbol = "km<sup>3</sup>/a", utype = "flow", scale = 31.68808781402895, default = "cumi/a", link = "Cubic metre per second", }, ["km3/d"] = { name1 = "cubic kilometre per day", name1_us = "cubic kilometer per day", name2 = "cubic kilometres per day", name2_us = "cubic kilometers per day", symbol = "km<sup>3</sup>/d", utype = "flow", scale = 11574.074074074075, default = "cuft/d", link = "Cubic metre per second", }, ["koilbbl/a"] = { name1 = "thousand barrels per year", name2 = "thousand barrels per year", symbol = "kbbl/a", utype = "flow", scale = 5.0380033629933841e-6, default = "v * 1.58987294928 < 10 ! ! e3 ! m3/a", link = "Barrel per day", }, ["koilbbl/d"] = { name1 = "thousand barrels per day", name2 = "thousand barrels per day", symbol = "kbbl/d", utype = "flow", scale = 0.0018401307283333335, default = "v * 1.58987294928 < 10 ! ! e3 ! m3/d", link = "Barrel per day", }, ["L/h"] = { name1 = "litre per hour", name1_us = "liter per hour", name2 = "litres per hour", name2_us = "liters per hour", symbol = "L/h", utype = "flow", scale = 2.7777777777777776e-7, default = "impgal/h USgal/h", link = "Cubic metre per second", }, ["L/min"] = { name1 = "litre per minute", name1_us = "liter per minute", name2 = "litres per minute", name2_us = "liters per minute", symbol = "L/min", utype = "flow", scale = 1.6666666666666667e-5, default = "impgal/min USgal/min", link = "Cubic metre per second", }, ["L/s"] = { name1 = "litre per second", name1_us = "liter per second", name2 = "litres per second", name2_us = "liters per second", symbol = "L/s", utype = "flow", scale = 0.001, default = "cuft/s", link = "Cubic metre per second", }, ["m3/a"] = { name1 = "cubic metre per annum", name1_us = "cubic meter per annum", name2 = "cubic metres per annum", name2_us = "cubic meters per annum", symbol = "m<sup>3</sup>/a", utype = "flow", scale = 3.1688087814028947e-8, default = "cuft/a", link = "Cubic metre per second", }, ["m3/d"] = { name1 = "cubic metre per day", name1_us = "cubic meter per day", name2 = "cubic metres per day", name2_us = "cubic meters per day", symbol = "m<sup>3</sup>/d", utype = "flow", scale = 1.1574074074074073e-5, default = "cuft/d", link = "Cubic metre per second", }, ["m3/h"] = { name1 = "cubic metre per hour", name1_us = "cubic meter per hour", name2 = "cubic metres per hour", name2_us = "cubic meters per hour", symbol = "m<sup>3</sup>/h", utype = "flow", scale = 0.00027777777777777778, default = "cuft/h", link = "Cubic metre per second", }, ["m3/min"] = { name1 = "cubic metre per minute", name1_us = "cubic meter per minute", name2 = "cubic metres per minute", name2_us = "cubic meters per minute", symbol = "m<sup>3</sup>/min", utype = "flow", scale = 0.016666666666666666, default = "cuft/min", link = "Cubic metre per second", }, ["m3/s"] = { name1 = "cubic metre per second", name1_us = "cubic meter per second", name2 = "cubic metres per second", name2_us = "cubic meters per second", symbol = "m<sup>3</sup>/s", utype = "flow", scale = 1, default = "cuft/s", }, ["Moilbbl/a"] = { name1 = "million barrels per year", name2 = "million barrels per year", symbol = "Mbbl/a", utype = "flow", scale = 0.0050380033629933837, default = "v * 1.58987294928 < 10 ! e3 ! e6 ! m3/a", link = "Barrel per day", }, ["Moilbbl/d"] = { name1 = "million barrels per day", name2 = "million barrels per day", symbol = "Mbbl/d", utype = "flow", scale = 1.8401307283333335, default = "v * 1.58987294928 < 10 ! e3 ! e6 ! m3/d", link = "Barrel per day", }, ["oilbbl/a"] = { name1 = "barrel per year", name2 = "barrels per year", symbol = "bbl/a", utype = "flow", scale = 5.0380033629933841e-9, default = "m3/a", link = "Barrel per day", }, ["oilbbl/d"] = { name1 = "barrel per day", name2 = "barrels per day", symbol = "bbl/d", utype = "flow", scale = 1.8401307283333336e-6, default = "m3/d", }, ["Toilbbl/a"] = { name1 = "trillion barrels per year", name2 = "trillion barrels per year", symbol = "Tbbl/a", utype = "flow", scale = 5038.0033629933832, default = "v * 1.58987294928 < 10 ! e9 ! e12 ! m3/a", link = "Barrel per day", }, ["U.S.gal/d"] = { name1 = "U.S. gallon per day", name2 = "U.S. gallons per day", symbol = "U.S.&nbsp;gal/d", utype = "flow", scale = 4.3812636388888893e-8, default = "m3/s", customary= 1, }, ["U.S.gal/h"] = { name1 = "gallon per hour", name2 = "gallons per hour", symbol = "gal/h", utype = "flow", scale = 1.0515032733333334e-6, default = "m3/h", link = "Gallon", customary= 2, }, ["U.S.gal/min"] = { name1 = "U.S. gallon per minute", name2 = "U.S. gallons per minute", symbol = "U.S.&nbsp;gal/min", utype = "flow", scale = 6.3090196400000003e-5, default = "m3/s", link = "Gallon", }, ["USgal/a"] = { name1 = "US gallon per year", name2 = "US gallons per year", symbol = "US&nbsp;gal/a", utype = "flow", scale = 1.1995246102365199e-10, default = "m3/s", }, ["USgal/d"] = { name1 = "US gallon per day", name2 = "US gallons per day", symbol = "US&nbsp;gal/d", utype = "flow", scale = 4.3812636388888893e-8, default = "m3/s", }, ["USgal/h"] = { name1 = "gallon per hour", name2 = "gallons per hour", symbol = "gal/h", utype = "flow", scale = 1.0515032733333334e-6, default = "m3/h", link = "Gallon", customary= 1, }, ["USgal/min"] = { name1 = "US gallon per minute", name2 = "US gallons per minute", symbol = "US&nbsp;gal/min", utype = "flow", scale = 6.3090196400000003e-5, default = "m3/s", link = "Gallon", }, ["USgal/s"] = { name1 = "US gallon per second", name1_us = "U.S. gallon per second", name2 = "US gallons per second", name2_us = "U.S. gallons per second", symbol = "USgal/s", utype = "flow", scale = 0.003785411784, default = "m3/s", link = "US gallons per second", }, ["ft3/a"] = { target = "cuft/a", }, ["ft3/d"] = { target = "cuft/d", }, ["ft3/h"] = { target = "cuft/h", }, ["ft3/s"] = { target = "cuft/s", }, ["Gcuft/a"] = { target = "e9cuft/a", }, ["Gcuft/d"] = { target = "e9cuft/d", }, ["kcuft/a"] = { target = "e3cuft/a", }, ["kcuft/d"] = { target = "e3cuft/d", }, ["kcuft/s"] = { target = "e3cuft/s", }, ["Mcuft/a"] = { target = "e6cuft/a", }, ["Mcuft/d"] = { target = "e6cuft/d", }, ["Mcuft/s"] = { target = "e6cuft/s", }, ["m³/s"] = { target = "m3/s", }, ["Tcuft/a"] = { target = "e12cuft/a", }, ["Tcuft/d"] = { target = "e12cuft/d", }, ["u.s.gal/min"] = { target = "U.S.gal/min", }, ["usgal/min"] = { target = "USgal/min", }, ["-LTf"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "LTf", utype = "force", scale = 9964.01641818352, default = "kN", }, ["-STf"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "STf", utype = "force", scale = 8896.443230521, default = "kN", }, ["dyn"] = { name1 = "dyne", symbol = "dyn", utype = "force", scale = 0.00001, default = "gr-f", }, ["g-f"] = { name1 = "gram-force", name2 = "grams-force", symbol = "g<sub>f</sub>", utype = "force", scale = 0.00980665, default = "mN oz-f", link = "Kilogram-force", }, ["gf"] = { name1 = "gram-force", name2 = "grams-force", symbol = "gf", utype = "force", scale = 0.00980665, default = "mN ozf", link = "Kilogram-force", }, ["gr-f"] = { name1 = "grain-force", name2 = "grains-force", symbol = "gr<sub>f</sub>", utype = "force", scale = 0.0006354602307515, default = "μN", link = "Pound (force)", }, ["grf"] = { name1 = "grain-force", name2 = "grains-force", symbol = "grf", utype = "force", scale = 0.0006354602307515, default = "μN", link = "Pound (force)", }, ["kdyn"] = { name1 = "kilodyne", symbol = "kdyn", utype = "force", scale = 0.01, default = "oz-f", link = "Dyne", }, ["kg-f"] = { name1 = "kilogram-force", name2 = "kilograms-force", symbol = "kg<sub>f</sub>", utype = "force", scale = 9.80665, default = "N lb-f", }, ["kgf"] = { name1 = "kilogram-force", name2 = "kilograms-force", symbol = "kgf", utype = "force", scale = 9.80665, default = "N lbf", }, ["kp"] = { name1 = "kilopond", symbol = "kp", utype = "force", scale = 9.80665, default = "N lb-f", link = "Kilogram-force", }, ["L/T-f"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "L/T<sub>f</sub>", utype = "force", scale = 9964.01641818352, default = "kN", }, ["L/Tf"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "L/Tf", utype = "force", scale = 9964.01641818352, default = "kN", }, ["lb-f"] = { name1 = "pound-force", name2 = "pounds-force", symbol = "lb<sub>f</sub>", utype = "force", scale = 4.4482216152605, default = "N", link = "Pound (force)", }, ["lbf"] = { name1 = "pound-force", name2 = "pounds-force", symbol = "lbf", utype = "force", scale = 4.4482216152605, default = "N", link = "Pound (force)", }, ["lb(f)"] = { name1 = "pound", symbol = "lb", utype = "force", scale = 4.4482216152605, default = "N", link = "Pound (force)", }, ["LT-f"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "LT<sub>f</sub>", utype = "force", scale = 9964.01641818352, default = "kN", }, ["LTf"] = { name1 = "long ton-force", name2 = "long tons-force", symbol = "LTf", usename = 1, utype = "force", scale = 9964.01641818352, default = "kN", }, ["Mdyn"] = { name1 = "megadyne", symbol = "Mdyn", utype = "force", scale = 10, default = "lb-f", link = "Dyne", }, ["mdyn"] = { name1 = "millidyne", symbol = "mdyn", utype = "force", scale = 0.00000001, default = "gr-f", link = "Dyne", }, ["mg-f"] = { name1 = "milligram-force", name2 = "milligrams-force", symbol = "mg<sub>f</sub>", utype = "force", scale = 0.00000980665, default = "μN gr-f", link = "Kilogram-force", }, ["mgf"] = { name1 = "milligram-force", name2 = "milligrams-force", symbol = "mgf", utype = "force", scale = 0.00000980665, default = "μN grf", link = "Kilogram-force", }, ["Mp"] = { name1 = "megapond", symbol = "Mp", utype = "force", scale = 9806.65, default = "kN LT-f ST-f", link = "Kilogram-force", }, ["mp"] = { name1 = "millipond", symbol = "mp", utype = "force", scale = 0.00000980665, default = "μN gr-f", link = "Kilogram-force", }, ["N"] = { _name1 = "newton", _symbol = "N", utype = "force", scale = 1, prefixes = 1, default = "lb-f", link = "Newton (unit)", }, ["oz-f"] = { name1 = "ounce-force", name2 = "ounces-force", symbol = "oz<sub>f</sub>", utype = "force", scale = 0.2780138203095378125, default = "mN", link = "Pound (force)", }, ["ozf"] = { name1 = "ounce-force", name2 = "ounces-force", symbol = "ozf", utype = "force", scale = 0.2780138203095378125, default = "mN", link = "Pound (force)", }, ["p"] = { name1 = "pond", symbol = "p", utype = "force", scale = 0.00980665, default = "mN oz-f", link = "Kilogram-force", }, ["pdl"] = { name1 = "poundal", symbol = "pdl", utype = "force", scale = 0.138254954376, default = "N", }, ["S/T-f"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "S/T<sub>f</sub>", utype = "force", scale = 8896.443230521, default = "kN", }, ["S/Tf"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "S/Tf", utype = "force", scale = 8896.443230521, default = "kN", }, ["ST-f"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "ST<sub>f</sub>", utype = "force", scale = 8896.443230521, default = "kN", }, ["STf"] = { name1 = "short ton-force", name2 = "short tons-force", symbol = "STf", usename = 1, utype = "force", scale = 8896.443230521, default = "kN", }, ["t-f"] = { name1 = "tonne-force", name2 = "tonnes-force", symbol = "t<sub>f</sub>", utype = "force", scale = 9806.65, default = "kN LT-f ST-f", link = "Ton-force#Tonne-force", }, ["tf"] = { name1 = "tonne-force", name2 = "tonnes-force", symbol = "tf", utype = "force", scale = 9806.65, default = "kN LTf STf", link = "Ton-force#Tonne-force", }, ["dyne"] = { target = "dyn", }, ["newtons"] = { target = "N", }, ["poundal"] = { target = "pdl", }, ["tonne-force"] = { target = "tf", }, ["impgal/mi"] = { per = { "@impgal", "mi" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "l/km USgal/mi", }, ["km/L"] = { per = { "km", "L" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "mpgimp mpgus", }, ["km/l"] = { per = { "km", "l" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "mpgimp mpgus", }, ["L/100 km"] = { per = { "L", "100km" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "mpgimp mpgus", symlink = "[[Fuel economy in automobiles#Units of measure|L/100&nbsp;km]]", }, ["l/100 km"] = { per = { "l", "100km" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "mpgimp mpgus", symlink = "[[Fuel economy in automobiles#Units of measure|l/100&nbsp;km]]", }, ["L/km"] = { per = { "L", "km" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "mpgimp mpgus", }, ["l/km"] = { per = { "l", "km" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "mpgimp mpgus", }, ["mi/impqt"] = { per = { "mi", "impqt" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "km/L", }, ["mi/U.S.qt"] = { per = { "mi", "U.S.qt" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "km/L", }, ["mi/USqt"] = { per = { "mi", "USqt" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "km/L", }, ["mi/usqt"] = { per = { "mi", "usqt" }, utype = "fuel efficiency", invert = -1, iscomplex= true, default = "km/L", }, ["mpgimp"] = { per = { "mi", "@impgal" }, symbol = "mpg<sub>&#8209;imp</sub>", utype = "fuel efficiency", invert = -1, iscomplex= true, default = "L/100 km+mpgus", symlink = "[[Fuel economy in automobiles#Units of measure|mpg]]<sub>&#8209;[[Imperial units|imp]]</sub>", }, ["mpgus"] = { per = { "mi", "+USgal" }, symbol = "mpg<sub>&#8209;US</sub>", utype = "fuel efficiency", invert = -1, iscomplex= true, default = "L/100 km+mpgimp", symlink = "[[Fuel economy in automobiles#Units of measure|mpg]]<sub>&#8209;[[United States customary units|US]]</sub>", }, ["U.S.gal/mi"] = { per = { "*U.S.gal", "mi" }, sp_us = true, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "l/km impgal/mi", }, ["usgal/mi"] = { per = { "+USgal", "mi" }, utype = "fuel efficiency", invert = 1, iscomplex= true, default = "l/km impgal/mi", }, ["L/100km"] = { target = "L/100 km", }, ["l/100km"] = { target = "l/100 km", }, ["mpg"] = { shouldbe = "Use %{mpgus%} for miles per US gallon or %{mpgimp%} for miles per imperial gallon (not %{mpg%})", }, ["mpgU.S."] = { target = "mpgus", symbol = "mpg<sub>&#8209;U.S.</sub>", sp_us = true, symlink = "[[Fuel economy in automobiles#Units of measure|mpg]]<sub>&#8209;[[United States customary units|U.S.]]</sub>", }, ["mpgu.s."] = { target = "mpgus", symbol = "mpg<sub>&#8209;U.S.</sub>", sp_us = true, symlink = "[[Fuel economy in automobiles#Units of measure|mpg]]<sub>&#8209;[[United States customary units|U.S.]]</sub>", }, ["mpgUS"] = { target = "mpgus", }, ["USgal/mi"] = { target = "usgal/mi", }, ["kPa/m"] = { per = { "kPa", "-m-frac" }, utype = "fracture gradient", default = "psi/ft", }, ["psi/ft"] = { per = { "psi", "-ft-frac" }, utype = "fracture gradient", default = "kPa/m", }, ["cm/km"] = { name1 = "centimetre per kilometre", name1_us = "centimeter per kilometer", name2 = "centimetres per kilometre", name2_us = "centimeters per kilometer", symbol = "cm/km", utype = "gradient", scale = 0.00001, default = "ft/mi", link = "Grade (slope)", }, ["ft/mi"] = { name1 = "foot per mile", name2 = "feet per mile", symbol = "ft/mi", utype = "gradient", scale = 0.00018939393939393939, default = "v < 5.28 ! c ! ! m/km", link = "Grade (slope)", }, ["ft/nmi"] = { name1 = "foot per nautical mile", name2 = "feet per nautical mile", symbol = "ft/nmi", utype = "gradient", scale = 0.00016457883369330455, default = "v < 6.076 ! c ! ! m/km", link = "Grade (slope)", }, ["in/ft"] = { name1 = "inch per foot", name2 = "inches per foot", symbol = "in/ft", utype = "gradient", scale = 0.083333333333333329, default = "mm/m", link = "Grade (slope)", }, ["in/mi"] = { name1 = "inch per mile", name2 = "inches per mile", symbol = "in/mi", utype = "gradient", scale = 1.5782828282828283e-5, default = "v < 0.6336 ! m ! c ! m/km", link = "Grade (slope)", }, ["m/km"] = { name1 = "metre per kilometre", name1_us = "meter per kilometer", name2 = "metres per kilometre", name2_us = "meters per kilometer", symbol = "m/km", utype = "gradient", scale = 0.001, default = "ft/mi", link = "Grade (slope)", }, ["mm/km"] = { name1 = "millimetre per kilometre", name1_us = "millimeter per kilometer", name2 = "millimetres per kilometre", name2_us = "millimeters per kilometer", symbol = "mm/km", utype = "gradient", scale = 0.000001, default = "in/mi", link = "Grade (slope)", }, ["mm/m"] = { name1 = "millimetre per metre", name1_us = "millimeter per meter", name2 = "millimetres per metre", name2_us = "millimeters per meter", symbol = "mm/m", utype = "gradient", scale = 0.001, default = "in/ft", link = "Grade (slope)", }, ["admi"] = { name1 = "admiralty mile", symbol = "nmi&nbsp;(admiralty)", utype = "length", scale = 1853.184, default = "km mi", link = "Nautical mile", }, ["AU"] = { name1 = "astronomical unit", symbol = "AU", utype = "length", scale = 149597870700, default = "km mi", }, ["Brnmi"] = { name1 = "British nautical mile", symbol = "(Brit)&nbsp;nmi", utype = "length", scale = 1853.184, default = "km mi", link = "Nautical mile", }, ["bu"] = { name2 = "bu", symbol = "bu", usename = 1, utype = "length", scale = 0.0030303030303030303, default = "mm", link = "Japanese units of measurement#Length", }, ["ch"] = { name1 = "chain", symbol = "ch", utype = "length", scale = 20.1168, default = "ft m", subdivs = { ["ft"] = { 66, default = "m" }, ["yd"] = { 22, default = "m" } }, link = "Chain (unit)", }, ["chlk"] = { name1 = "[[Chain (unit)|chain]]", symbol = "[[Chain (unit)|ch]]", utype = "length", scale = 20.1168, default = "ft m", link = "", }, ["chain"] = { symbol = "chain", usename = 1, utype = "length", scale = 20.1168, default = "ft m", subdivs = { ["ft"] = { 66, default = "m" }, ["yd"] = { 22, default = "m" } }, link = "Chain (unit)", }, ["chainlk"] = { symbol = "[[Chain (unit)|chain]]", usename = 1, utype = "length", scale = 20.1168, default = "ft m", link = "", }, ["dpcm"] = { name2 = "dot/cm", symbol = "dot/cm", utype = "length", scale = 100, invert = -1, iscomplex= true, default = "dpi", link = "Dots per inch", }, ["dpi"] = { name2 = "DPI", symbol = "DPI", utype = "length", scale = 39.370078740157481, invert = -1, iscomplex= true, default = "pitch", link = "Dots per inch", }, ["fathom"] = { symbol = "fathom", usename = 1, utype = "length", scale = 1.8288, default = "ft m", }, ["foot"] = { name1 = "foot", name2 = "foot", symbol = "ft", utype = "length", scale = 0.3048, default = "m", subdivs = { ["in"] = { 12, default = "m" } }, link = "Foot (unit)", }, ["ft"] = { name1 = "foot", name2 = "feet", symbol = "ft", utype = "length", scale = 0.3048, exception= "integer_more_precision", default = "m", subdivs = { ["in"] = { 12, default = "m" } }, link = "Foot (unit)", }, ["furlong"] = { symbol = "furlong", usename = 1, utype = "length", scale = 201.168, default = "ft m", }, ["Gly"] = { name1 = "gigalight-year", symbol = "Gly", utype = "length", scale = 9.4607304725808e24, default = "Mpc", link = "Light-year#Definitions", }, ["Gpc"] = { name1 = "gigaparsec", symbol = "Gpc", utype = "length", scale = 3.0856775814671916e25, default = "Gly", link = "Parsec#Megaparsecs and gigaparsecs", }, ["hand"] = { name1 = "hand", symbol = "h", utype = "length", builtin = "hand", scale = 0.1016, iscomplex= true, default = "in cm", link = "Hand (unit)", }, ["in"] = { name1 = "inch", name2 = "inches", symbol = "in", utype = "length", scale = 0.0254, exception= "subunit_more_precision", default = "mm", }, ["inabbreviated"] = { name2 = "in", symbol = "in", utype = "length", scale = 0.0254, default = "mm", link = "Inch", }, ["kly"] = { name1 = "kilolight-year", symbol = "kly", utype = "length", scale = 9.4607304725808e18, default = "pc", link = "Light-year#Definitions", }, ["kpc"] = { name1 = "kiloparsec", symbol = "kpc", utype = "length", scale = 3.0856775814671916e19, default = "kly", link = "Parsec#Parsecs and kiloparsecs", }, ["LD"] = { name1 = "lunar distance", symbol = "LD", utype = "length", scale = 384403000, default = "km mi", link = "Lunar distance (astronomy)", }, ["league"] = { symbol = "league", usename = 1, utype = "length", scale = 4828.032, default = "km", link = "League (unit)", }, ["ly"] = { name1 = "light-year", symbol = "ly", utype = "length", scale = 9.4607304725808e15, default = "AU", }, ["m"] = { _name1 = "metre", _name1_us= "meter", _symbol = "m", utype = "length", scale = 1, prefixes = 1, default = "v > 0 and v < 3 ! ftin ! ft", link = "Metre", }, ["mi"] = { name1 = "mile", symbol = "mi", utype = "length", scale = 1609.344, default = "km", subdivs = { ["ch"] = { 80, default = "km" }, ["chlk"] = { 80, default = "km" }, ["chain"] = { 80, default = "km" }, ["chainlk"] = { 80, default = "km" }, ["ft"] = { 5280, default = "km" }, ["furlong"] = { 8, default = "km" }, ["yd"] = { 1760, default = "km" } }, }, ["mil"] = { symbol = "mil", usename = 1, utype = "length", scale = 0.0000254, default = "mm", link = "Thousandth of an inch", }, ["Mly"] = { name1 = "megalight-year", symbol = "Mly", utype = "length", scale = 9.4607304725808e21, default = "kpc", link = "Light-year#Definitions", }, ["Mpc"] = { name1 = "megaparsec", symbol = "Mpc", utype = "length", scale = 3.0856775814671916e22, default = "Mly", link = "Parsec#Megaparsecs and gigaparsecs", }, ["NM"] = { name1 = "nautical mile", symbol = "NM", utype = "length", scale = 1852, default = "km mi", }, ["nmi"] = { name1 = "nautical mile", symbol = "nmi", utype = "length", scale = 1852, default = "km mi", }, ["oldUKnmi"] = { name1 = "nautical mile", symbol = "nmi", utype = "length", scale = 1853.184, default = "km mi", }, ["oldUSnmi"] = { name1 = "nautical mile", symbol = "nmi", utype = "length", scale = 1853.24496, default = "km mi", }, ["pc"] = { name1 = "parsec", symbol = "pc", utype = "length", scale = 3.0856775814671916e16, default = "ly", }, ["perch"] = { name2 = "perches", symbol = "perch", usename = 1, utype = "length", scale = 5.0292, default = "ft m", link = "Rod (unit)", }, ["pitch"] = { name2 = "μm", symbol = "μm", utype = "length", scale = 1e-6, default = "dpi", defkey = "pitch", linkey = "pitch", link = "Dots per inch", }, ["pole"] = { symbol = "pole", usename = 1, utype = "length", scale = 5.0292, default = "ft m", link = "Rod (unit)", }, ["pre1954U.S.nmi"] = { name1 = "(pre-1954&nbsp;U.S.) nautical mile", symbol = "(pre&#8209;1954&nbsp;U.S.) nmi", utype = "length", scale = 1853.24496, default = "km mi", link = "Nautical mile", }, ["pre1954USnmi"] = { name1 = "(pre-1954&nbsp;US) nautical mile", name1_us = "(pre-1954&nbsp;U.S.) nautical mile", symbol = "(pre&#8209;1954&nbsp;US) nmi", sym_us = "(pre&#8209;1954&nbsp;U.S.) nmi", utype = "length", scale = 1853.24496, default = "km mi", link = "Nautical mile", }, ["rd"] = { name1 = "rod", symbol = "rd", utype = "length", scale = 5.0292, default = "ft m", link = "Rod (unit)", }, ["royal cubit"] = { name1 = "royal cubit", symbol = "cu", utype = "length", scale = 0.524, default = "mm", }, ["rtkm"] = { name1 = "route kilometre", name1_us = "route kilometer", symbol = "km", utype = "length", scale = 1000, default = "mi", link = "Kilometre", }, ["rtmi"] = { name1 = "route mile", symbol = "mi", utype = "length", scale = 1609.344, default = "km", link = "Mile", }, ["shaku"] = { name2 = "shaku", symbol = "shaku", usename = 1, utype = "length", scale = 0.30303030303030304, default = "m", link = "Shaku (unit)", }, ["sm"] = { name1 = "smoot", symbol = "sm", utype = "length", scale = 1.70180, default = "m", link = "Smoot (unit)", }, ["smi"] = { name1 = "statute mile", symbol = "mi", utype = "length", scale = 1609.344, default = "km", subdivs = { ["chain"] = { 80, default = "km" } }, }, ["solar radius"] = { name1 = "solar radius", name2 = "solar radii", symbol = "''R''<sub>☉</sub>", utype = "length", scale = 695700e3, default = "km", }, ["sun"] = { name2 = "sun", symbol = "sun", usename = 1, utype = "length", scale = 0.030303030303030304, default = "mm", link = "Japanese units of measurement#Length", }, ["thou"] = { name2 = "thou", symbol = "thou", usename = 1, utype = "length", scale = 0.0000254, default = "mm", link = "Thousandth of an inch", }, ["verst"] = { symbol = "verst", usename = 1, utype = "length", scale = 1066.8, default = "km mi", }, ["yd"] = { name1 = "yard", symbol = "yd", utype = "length", scale = 0.9144, default = "m", subdivs = { ["ft"] = { 3, default = "m" } }, }, ["μin"] = { name1 = "microinch", name2 = "microinches", symbol = "μin", utype = "length", scale = 0.0000000254, default = "nm", link = "SI prefix#Non-metric units", }, ["Å"] = { name1 = "ångström", symbol = "Å", utype = "length", scale = 0.0000000001, default = "in", }, ["Hz"] = { _name1 = "hertz", _name2 = "hertz", _symbol = "Hz", utype = "length", scale = 3.3356409519815204e-9, invert = -1, iscomplex= true, prefixes = 1, default = "m", link = "Hertz", }, ["rpm"] = { name1 = "revolution per minute", name2 = "revolutions per minute", symbol = "rpm", utype = "length", scale = 5.5594015866358675e-11, invert = -1, iscomplex= true, default = "Hz", link = "Revolutions per minute", }, ["-ft-frac"] = { target = "ft", link = "Fracture gradient", }, ["-in-stiff"] = { target = "in", link = "Stiffness", }, ["-m-frac"] = { target = "m", link = "Fracture gradient", }, ["-m-stiff"] = { target = "m", link = "Stiffness", }, ["100km"] = { target = "km", multiplier= 100, }, ["100mi"] = { target = "mi", multiplier= 100, }, ["100miles"] = { target = "mi", symbol = "miles", multiplier= 100, }, ["admiralty nmi"] = { target = "oldUKnmi", }, ["angstrom"] = { target = "Å", }, ["au"] = { target = "AU", symbol = "au", }, ["feet"] = { target = "ft", }, ["hands"] = { target = "hand", }, ["inch"] = { target = "in", }, ["light-year"] = { target = "ly", }, ["meter"] = { target = "m", sp_us = true, }, ["meters"] = { target = "m", sp_us = true, }, ["metre"] = { target = "m", }, ["metres"] = { target = "m", }, ["micrometre"] = { target = "μm", }, ["micron"] = { target = "μm", default = "μin", }, ["mile"] = { target = "mi", }, ["miles"] = { target = "mi", }, ["parsec"] = { target = "pc", }, ["rod"] = { target = "rd", }, ["smoot"] = { target = "sm", }, ["uin"] = { target = "μin", }, ["yard"] = { target = "yd", }, ["yards"] = { target = "yd", }, ["yds"] = { target = "yd", }, ["dtex"] = { name1 = "decitex", name2 = "decitex", symbol = "dtex", utype = "linear density", scale = 1e-7, default = "lb/yd", link = "Units of textile measurement#Units", }, ["kg/cm"] = { name1 = "kilogram per centimetre", name1_us = "kilogram per centimeter", name2 = "kilograms per centimetre", name2_us = "kilograms per centimeter", symbol = "kg/cm", utype = "linear density", scale = 100, default = "lb/yd", link = "Linear density", }, ["kg/m"] = { name1 = "kilogram per metre", name1_us = "kilogram per meter", name2 = "kilograms per metre", name2_us = "kilograms per meter", symbol = "kg/m", utype = "linear density", scale = 1, default = "lb/yd", link = "Linear density", }, ["lb/ft"] = { name1 = "pound per foot", name2 = "pounds per foot", symbol = "lb/ft", utype = "linear density", scale = 1.4881639435695539, default = "kg/m", link = "Linear density", }, ["lb/yd"] = { name1 = "pound per yard", name2 = "pounds per yard", symbol = "lb/yd", utype = "linear density", scale = 0.49605464785651798, default = "kg/m", link = "Linear density", }, ["G"] = { _name1 = "gauss", _name2 = "gauss", _symbol = "G", utype = "magnetic field strength", scale = 0.0001, prefixes = 1, default = "T", link = "Gauss (unit)", }, ["T"] = { _name1 = "tesla", _symbol = "T", utype = "magnetic field strength", scale = 1, prefixes = 1, default = "G", link = "Tesla (unit)", }, ["A/m"] = { name1 = "ampere per metre", name1_us = "ampere per meter", name2 = "amperes per metre", name2_us = "amperes per meter", symbol = "A/m", utype = "magnetizing field", scale = 1, default = "Oe", }, ["kA/m"] = { name1 = "kiloampere per metre", name1_us = "kiloampere per meter", name2 = "kiloamperes per metre", name2_us = "kiloamperes per meter", symbol = "kA/m", utype = "magnetizing field", scale = 1000, default = "kOe", link = "Ampere per metre", }, ["MA/m"] = { name1 = "megaampere per metre", name1_us = "megaampere per meter", name2 = "megaamperes per metre", name2_us = "megaamperes per meter", symbol = "MA/m", utype = "magnetizing field", scale = 1e6, default = "kOe", link = "Ampere per metre", }, ["Oe"] = { _name1 = "oersted", _symbol = "Oe", utype = "magnetizing field", scale = 79.5774715, prefixes = 1, default = "kA/m", link = "Oersted", }, ["-Lcwt"] = { name1 = "hundredweight", name2 = "hundredweight", symbol = "cwt", utype = "mass", scale = 50.80234544, default = "lb", }, ["-Scwt"] = { name1 = "hundredweight", name2 = "hundredweight", symbol = "cwt", utype = "mass", scale = 45.359237, default = "lb", }, ["-ST"] = { name1 = "short ton", symbol = "ST", utype = "mass", scale = 907.18474, default = "t", }, ["carat"] = { symbol = "carat", usename = 1, utype = "mass", scale = 0.0002, default = "g", link = "Carat (mass)", }, ["drachm"] = { name1_us = "dram", symbol = "drachm", usename = 1, utype = "mass", scale = 0.001771845195, default = "g", link = "Dram (unit)", }, ["dram"] = { target = "drachm", }, ["dwt"] = { name1 = "pennyweight", symbol = "dwt", utype = "mass", scale = 0.00155517384, default = "oz g", }, ["DWton"] = { symbol = "deadweight ton", usename = 1, utype = "mass", scale = 1016.0469088, default = "DWtonne", link = "Deadweight tonnage", }, ["DWtonne"] = { symbol = "deadweight tonne", usename = 1, utype = "mass", scale = 1000, default = "DWton", link = "Deadweight tonnage", }, ["g"] = { _name1 = "gram", _symbol = "g", utype = "mass", scale = 0.001, prefixes = 1, default = "oz", link = "Gram", }, ["gr"] = { name1 = "grain", symbol = "gr", utype = "mass", scale = 0.00006479891, default = "g", link = "Grain (unit)", }, ["Gt"] = { name1 = "gigatonne", symbol = "Gt", utype = "mass", scale = 1000000000000, default = "LT ST", link = "Tonne", }, ["impgalh2o"] = { name1 = "imperial gallon of water", name2 = "imperial gallons of water", symbol = "imp&nbsp;gal H<sub>2</sub>O", utype = "mass", scale = 4.5359236999999499, default = "lb kg", link = "Imperial gallon", }, ["kt"] = { name1 = "kilotonne", symbol = "kt", utype = "mass", scale = 1000000, default = "LT ST", link = "Tonne", }, ["lb"] = { name1 = "pound", symbol = "lb", utype = "mass", scale = 0.45359237, exception= "integer_more_precision", default = "kg", subdivs = { ["oz"] = { 16, default = "kg" } }, link = "Pound (mass)", }, ["Lcwt"] = { name1 = "long hundredweight", name2 = "long hundredweight", symbol = "Lcwt", usename = 1, utype = "mass", scale = 50.80234544, default = "lb", subdivs = { ["qtr"] = { 4, default = "kg" }, ["st"] = { 8, default = "kg" } }, link = "Hundredweight", }, ["long cwt"] = { name1 = "long hundredweight", name2 = "long hundredweight", symbol = "long&nbsp;cwt", utype = "mass", scale = 50.80234544, default = "lb kg", subdivs = { ["qtr"] = { 4, default = "kg" } }, link = "Hundredweight", }, ["long qtr"] = { name1 = "long quarter", symbol = "long&nbsp;qtr", utype = "mass", scale = 12.70058636, default = "lb kg", }, ["LT"] = { symbol = "long ton", usename = 1, utype = "mass", scale = 1016.0469088, default = "t", subdivs = { ["Lcwt"] = { 20, default = "t", unit = "-Lcwt" } }, }, ["lt"] = { name1 = "long ton", symbol = "LT", utype = "mass", scale = 1016.0469088, default = "t", subdivs = { ["Lcwt"] = { 20, default = "t", unit = "-Lcwt" } }, }, ["metric ton"] = { symbol = "metric ton", usename = 1, utype = "mass", scale = 1000, default = "long ton", link = "Tonne", }, ["MT"] = { name1 = "metric ton", symbol = "t", utype = "mass", scale = 1000, default = "LT ST", link = "Tonne", }, ["Mt"] = { name1 = "megatonne", symbol = "Mt", utype = "mass", scale = 1000000000, default = "LT ST", link = "Tonne", }, ["oz"] = { name1 = "ounce", symbol = "oz", utype = "mass", scale = 0.028349523125, default = "g", }, ["ozt"] = { name1 = "troy ounce", symbol = "ozt", utype = "mass", scale = 0.0311034768, default = "oz g", }, ["pdr"] = { name1 = "pounder", symbol = "pdr", utype = "mass", scale = 0.45359237, default = "kg", link = "Pound (mass)", }, ["qtr"] = { name1 = "quarter", symbol = "qtr", utype = "mass", scale = 12.70058636, default = "lb kg", subdivs = { ["lb"] = { 28, default = "kg" } }, link = "Long quarter", }, ["Scwt"] = { name1 = "short hundredweight", name2 = "short hundredweight", symbol = "Scwt", usename = 1, utype = "mass", scale = 45.359237, default = "lb", link = "Hundredweight", }, ["short cwt"] = { name1 = "short hundredweight", name2 = "short hundredweight", symbol = "short&nbsp;cwt", utype = "mass", scale = 45.359237, default = "lb kg", link = "Hundredweight", }, ["short qtr"] = { name1 = "short quarter", symbol = "short&nbsp;qtr", utype = "mass", scale = 11.33980925, default = "lb kg", }, ["ST"] = { symbol = "short ton", usename = 1, utype = "mass", scale = 907.18474, default = "t", subdivs = { ["Scwt"] = { 20, default = "t", unit = "-Scwt" } }, }, ["shtn"] = { name1 = "short ton", symbol = "sh&nbsp;tn", utype = "mass", scale = 907.18474, default = "t", }, ["shton"] = { symbol = "ton", usename = 1, utype = "mass", scale = 907.18474, default = "t", }, ["solar mass"] = { name1 = "solar mass", name2 = "solar masses", symbol = "''M''<sub>☉</sub>", utype = "mass", scale = 1.98855e30, default = "kg", }, ["st"] = { name1 = "stone", name2 = "stone", symbol = "st", utype = "mass", scale = 6.35029318, default = "lb kg", subdivs = { ["lb"] = { 14, default = "kg lb" } }, link = "Stone (unit)", }, ["t"] = { name1 = "tonne", name1_us = "metric ton", symbol = "t", utype = "mass", scale = 1000, default = "LT ST", }, ["tonne"] = { name1 = "tonne", name1_us = "metric ton", symbol = "t", utype = "mass", scale = 1000, default = "shton", }, ["troy pound"] = { symbol = "troy pound", usename = 1, utype = "mass", scale = 0.3732417216, default = "lb kg", link = "Troy weight", }, ["usgalh2o"] = { name1 = "US gallon of water", name1_us = "U.S. gallon of water", name2 = "US gallons of water", name2_us = "U.S. gallons of water", symbol = "US&nbsp;gal H<sub>2</sub>O", utype = "mass", scale = 3.7776215836051126, default = "lb kg", link = "United States customary units#Fluid volume", }, ["viss"] = { name2 = "viss", symbol = "viss", utype = "mass", scale = 1.632932532, default = "kg", link = "Myanmar units of measurement#Mass", }, ["billion tonne"] = { target = "e9t", }, ["kilogram"] = { target = "kg", }, ["kilotonne"] = { target = "kt", }, ["lbs"] = { target = "lb", }, ["lbt"] = { target = "troy pound", }, ["lcwt"] = { target = "Lcwt", }, ["long ton"] = { target = "LT", }, ["mcg"] = { target = "μg", }, ["million tonne"] = { target = "e6t", }, ["scwt"] = { target = "Scwt", }, ["short ton"] = { target = "ST", }, ["stone"] = { target = "st", }, ["thousand tonne"] = { target = "e3t", }, ["tonnes"] = { target = "t", }, ["kg/kW"] = { name1 = "kilogram per kilowatt", name2 = "kilograms per kilowatt", symbol = "kg/kW", utype = "mass per unit power", scale = 0.001, default = "lb/hp", link = "Kilowatt", }, ["lb/hp"] = { name1 = "pound per horsepower", name2 = "pounds per horsepower", symbol = "lb/hp", utype = "mass per unit power", scale = 0.00060827738784176115, default = "kg/kW", link = "Horsepower", }, ["kg/h"] = { per = { "kg", "h" }, utype = "mass per unit time", default = "lb/h", }, ["lb/h"] = { per = { "lb", "h" }, utype = "mass per unit time", default = "kg/h", }, ["g-mol/d"] = { name1 = "gram-mole per day", name2 = "gram-moles per day", symbol = "g&#8209;mol/d", utype = "molar rate", scale = 1.1574074074074073e-5, default = "μmol/s", link = "Mole (unit)", }, ["g-mol/h"] = { name1 = "gram-mole per hour", name2 = "gram-moles per hour", symbol = "g&#8209;mol/h", utype = "molar rate", scale = 0.00027777777777777778, default = "mmol/s", link = "Mole (unit)", }, ["g-mol/min"] = { name1 = "gram-mole per minute", name2 = "gram-moles per minute", symbol = "g&#8209;mol/min", utype = "molar rate", scale = 0.016666666666666666, default = "g-mol/s", link = "Mole (unit)", }, ["g-mol/s"] = { name1 = "gram-mole per second", name2 = "gram-moles per second", symbol = "g&#8209;mol/s", utype = "molar rate", scale = 1, default = "lb-mol/min", link = "Mole (unit)", }, ["gmol/d"] = { name1 = "gram-mole per day", name2 = "gram-moles per day", symbol = "gmol/d", utype = "molar rate", scale = 1.1574074074074073e-5, default = "μmol/s", link = "Mole (unit)", }, ["gmol/h"] = { name1 = "gram-mole per hour", name2 = "gram-moles per hour", symbol = "gmol/h", utype = "molar rate", scale = 0.00027777777777777778, default = "mmol/s", link = "Mole (unit)", }, ["gmol/min"] = { name1 = "gram-mole per minute", name2 = "gram-moles per minute", symbol = "gmol/min", utype = "molar rate", scale = 0.016666666666666666, default = "gmol/s", link = "Mole (unit)", }, ["gmol/s"] = { name1 = "gram-mole per second", name2 = "gram-moles per second", symbol = "gmol/s", utype = "molar rate", scale = 1, default = "lbmol/min", link = "Mole (unit)", }, ["kmol/d"] = { name1 = "kilomole per day", name2 = "kilomoles per day", symbol = "kmol/d", utype = "molar rate", scale = 0.011574074074074073, default = "mmol/s", link = "Mole (unit)", }, ["kmol/h"] = { name1 = "kilomole per hour", name2 = "kilomoles per hour", symbol = "kmol/h", utype = "molar rate", scale = 0.27777777777777779, default = "mol/s", link = "Mole (unit)", }, ["kmol/min"] = { name1 = "kilomole per minute", name2 = "kilomoles per minute", symbol = "kmol/min", utype = "molar rate", scale = 16.666666666666668, default = "mol/s", link = "Kilomole (unit)", }, ["kmol/s"] = { name1 = "kilomole per second", name2 = "kilomoles per second", symbol = "kmol/s", utype = "molar rate", scale = 1000, default = "lb-mol/s", link = "Mole (unit)", }, ["lb-mol/d"] = { name1 = "pound-mole per day", name2 = "pound-moles per day", symbol = "lb&#8209;mol/d", utype = "molar rate", scale = 0.0052499116898148141, default = "mmol/s", link = "Pound-mole", }, ["lb-mol/h"] = { name1 = "pound-mole per hour", name2 = "pound-moles per hour", symbol = "lb&#8209;mol/h", utype = "molar rate", scale = 0.12599788055555555, default = "mol/s", link = "Pound-mole", }, ["lb-mol/min"] = { name1 = "pound-mole per minute", name2 = "pound-moles per minute", symbol = "lb&#8209;mol/min", utype = "molar rate", scale = 7.5598728333333334, default = "mol/s", link = "Pound-mole", }, ["lb-mol/s"] = { name1 = "pound-mole per second", name2 = "pound-moles per second", symbol = "lb&#8209;mol/s", utype = "molar rate", scale = 453.59237, default = "kmol/s", link = "Pound-mole", }, ["lbmol/d"] = { name1 = "pound-mole per day", name2 = "pound-moles per day", symbol = "lbmol/d", utype = "molar rate", scale = 0.0052499116898148141, default = "mmol/s", link = "Pound-mole", }, ["lbmol/h"] = { name1 = "pound-mole per hour", name2 = "pound-moles per hour", symbol = "lbmol/h", utype = "molar rate", scale = 0.12599788055555555, default = "mol/s", link = "Pound-mole", }, ["lbmol/min"] = { name1 = "pound-mole per minute", name2 = "pound-moles per minute", symbol = "lbmol/min", utype = "molar rate", scale = 7.5598728333333334, default = "mol/s", link = "Pound-mole", }, ["lbmol/s"] = { name1 = "pound-mole per second", name2 = "pound-moles per second", symbol = "lbmol/s", utype = "molar rate", scale = 453.59237, default = "kmol/s", link = "Pound-mole", }, ["mmol/s"] = { name1 = "millimole per second", name2 = "millimoles per second", symbol = "mmol/s", utype = "molar rate", scale = 0.001, default = "lb-mol/d", link = "Mole (unit)", }, ["mol/d"] = { name1 = "mole per day", name2 = "moles per day", symbol = "mol/d", utype = "molar rate", scale = 1.1574074074074073e-5, default = "μmol/s", link = "Mole (unit)", }, ["mol/h"] = { name1 = "mole per hour", name2 = "moles per hour", symbol = "mol/h", utype = "molar rate", scale = 0.00027777777777777778, default = "mmol/s", link = "Mole (unit)", }, ["mol/min"] = { name1 = "mole per minute", name2 = "moles per minute", symbol = "mol/min", utype = "molar rate", scale = 0.016666666666666666, default = "mol/s", link = "Mole (unit)", }, ["mol/s"] = { name1 = "mole per second", name2 = "moles per second", symbol = "mol/s", utype = "molar rate", scale = 1, default = "lb-mol/min", link = "Mole (unit)", }, ["μmol/s"] = { name1 = "micromole per second", name2 = "micromoles per second", symbol = "μmol/s", utype = "molar rate", scale = 0.000001, default = "lb-mol/d", link = "Mole (unit)", }, ["umol/s"] = { target = "μmol/s", }, ["/acre"] = { name1 = "per acre", name2 = "per acre", symbol = "/acre", utype = "per unit area", scale = 0.00024710538146716532, default = "/ha", link = "Acre", }, ["/ha"] = { name1 = "per hectare", name2 = "per hectare", symbol = "/ha", utype = "per unit area", scale = 100e-6, default = "/acre", link = "Hectare", }, ["/sqcm"] = { name1 = "per square centimetre", name1_us = "per square centimeter", name2 = "per square centimetre", name2_us = "per square centimeter", symbol = "/cm<sup>2</sup>", utype = "per unit area", scale = 1e4, default = "/sqin", link = "Square centimetre", }, ["/sqin"] = { name1 = "per square inch", name2 = "per square inch", symbol = "/in<sup>2</sup>", utype = "per unit area", scale = 1550.0031000062002, default = "/sqcm", link = "Square inch", }, ["/sqkm"] = { name1 = "per square kilometre", name1_us = "per square kilometer", name2 = "per square kilometre", name2_us = "per square kilometer", symbol = "/km<sup>2</sup>", utype = "per unit area", scale = 1e-6, default = "/sqmi", link = "Square kilometre", }, ["/sqmi"] = { name1 = "per square mile", name2 = "per square mile", symbol = "/sq&nbsp;mi", utype = "per unit area", scale = 3.8610215854244582e-7, default = "/sqkm", link = "Square mile", }, ["PD/acre"] = { name1 = "inhabitant per acre", name2 = "inhabitants per acre", symbol = "/acre", utype = "per unit area", scale = 0.00024710538146716532, default = "PD/ha", link = "Acre", }, ["PD/ha"] = { name1 = "inhabitant per hectare", name2 = "inhabitants per hectare", symbol = "/ha", utype = "per unit area", scale = 100e-6, default = "PD/acre", link = "Hectare", }, ["PD/sqkm"] = { name1 = "inhabitant per square kilometre", name1_us = "inhabitant per square kilometer", name2 = "inhabitants per square kilometre", name2_us = "inhabitants per square kilometer", symbol = "/km<sup>2</sup>", utype = "per unit area", scale = 1e-6, default = "PD/sqmi", link = "Square kilometre", }, ["PD/sqmi"] = { name1 = "inhabitant per square mile", name2 = "inhabitants per square mile", symbol = "/sq&nbsp;mi", utype = "per unit area", scale = 3.8610215854244582e-7, default = "PD/sqkm", link = "Square mile", }, ["/cm2"] = { target = "/sqcm", }, ["/in2"] = { target = "/sqin", }, ["/km2"] = { target = "/sqkm", }, ["pd/acre"] = { target = "PD/acre", }, ["pd/ha"] = { target = "PD/ha", }, ["PD/km2"] = { target = "PD/sqkm", }, ["pd/km2"] = { target = "PD/sqkm", }, ["PD/km²"] = { target = "PD/sqkm", }, ["pd/sqkm"] = { target = "PD/sqkm", }, ["pd/sqmi"] = { target = "PD/sqmi", }, ["/l"] = { name1 = "per litre", name1_us = "per liter", name2 = "per litre", name2_us = "per liter", symbol = "/l", utype = "per unit volume", scale = 1000, default = "/usgal", link = "Litre", }, ["/USgal"] = { name1 = "per gallon", name2 = "per gallon", symbol = "/gal", utype = "per unit volume", scale = 264.172052, default = "/l", link = "US gallon", customary= 2, }, ["/usgal"] = { target = "/USgal", }, ["bhp"] = { name1 = "brake horsepower", name2 = "brake horsepower", symbol = "bhp", utype = "power", scale = 745.69987158227022, default = "kW", link = "Horsepower#Brake horsepower", }, ["Cal/d"] = { name1 = "large calorie per day", name2 = "large calories per day", symbol = "Cal/d", utype = "power", scale = 0.048425925925925928, default = "kJ/d", link = "Calorie", }, ["Cal/h"] = { name1 = "large calorie per hour", name2 = "large calories per hour", symbol = "Cal/h", utype = "power", scale = 1.1622222222222223, default = "kJ/h", link = "Calorie", }, ["cal/h"] = { name1 = "calorie per hour", name2 = "calories per hour", symbol = "cal/h", utype = "power", scale = 0.0011622222222222223, default = "W", link = "Calorie", }, ["CV"] = { name1 = "metric horsepower", name2 = "metric horsepower", symbol = "CV", utype = "power", scale = 735.49875, default = "kW", }, ["hk"] = { name1 = "metric horsepower", name2 = "metric horsepower", symbol = "hk", utype = "power", scale = 735.49875, default = "kW", }, ["hp"] = { name1 = "horsepower", name2 = "horsepower", symbol = "hp", utype = "power", scale = 745.69987158227022, default = "kW", }, ["hp-electric"] = { name1 = "electric horsepower", name2 = "electric horsepower", symbol = "hp", utype = "power", scale = 746, default = "kW", link = "Horsepower#Electrical horsepower", }, ["hp-electrical"] = { name1 = "electrical horsepower", name2 = "electrical horsepower", symbol = "hp", utype = "power", scale = 746, default = "kW", link = "Horsepower#Electrical horsepower", }, ["hp-metric"] = { name1 = "metric horsepower", name2 = "metric horsepower", symbol = "hp", utype = "power", scale = 735.49875, default = "kW", }, ["ihp"] = { name1 = "indicated horsepower", name2 = "indicated horsepower", symbol = "ihp", utype = "power", scale = 745.69987158227022, default = "kW", link = "Horsepower#Indicated horsepower", }, ["kcal/h"] = { name1 = "kilocalorie per hour", name2 = "kilocalories per hour", symbol = "kcal/h", utype = "power", scale = 1.1622222222222223, default = "kW", link = "Calorie", }, ["kJ/d"] = { name1 = "kilojoule per day", name2 = "kilojoules per day", symbol = "kJ/d", utype = "power", scale = 0.011574074074074073, default = "Cal/d", link = "Kilojoule", }, ["kJ/h"] = { name1 = "kilojoule per hour", name2 = "kilojoules per hour", symbol = "kJ/h", utype = "power", scale = 0.27777777777777779, default = "W", link = "Kilojoule", }, ["PS"] = { name1 = "metric horsepower", name2 = "metric horsepower", symbol = "PS", utype = "power", scale = 735.49875, default = "kW", }, ["shp"] = { name1 = "shaft horsepower", name2 = "shaft horsepower", symbol = "shp", utype = "power", scale = 745.69987158227022, default = "kW", link = "Horsepower#Shaft horsepower", }, ["W"] = { _name1 = "watt", _symbol = "W", utype = "power", scale = 1, prefixes = 1, default = "hp", link = "Watt", }, ["BTU/h"] = { per = { "BTU", "h" }, utype = "power", default = "W", }, ["Btu/h"] = { per = { "Btu", "h" }, utype = "power", default = "W", }, ["BHP"] = { target = "bhp", }, ["btu/h"] = { target = "BTU/h", }, ["HP"] = { target = "hp", }, ["Hp"] = { target = "hp", }, ["hp-mechanical"] = { target = "hp", }, ["IHP"] = { target = "ihp", }, ["SHP"] = { target = "shp", }, ["whp"] = { target = "hp", }, ["hp/lb"] = { name1 = "horsepower per pound", name2 = "horsepower per pound", symbol = "hp/lb", utype = "power per unit mass", scale = 1643.986806, default = "kW/kg", link = "Power-to-weight ratio", }, ["hp/LT"] = { name1 = "horsepower per long ton", name2 = "horsepower per long ton", symbol = "hp/LT", utype = "power per unit mass", scale = 0.73392268125000004, default = "kW/t", link = "Power-to-weight ratio", }, ["hp/ST"] = { name1 = "horsepower per short ton", name2 = "horsepower per short ton", symbol = "hp/ST", utype = "power per unit mass", scale = 0.821993403, default = "kW/t", link = "Power-to-weight ratio", }, ["hp/t"] = { name1 = "horsepower per tonne", name2 = "horsepower per tonne", symbol = "hp/t", utype = "power per unit mass", scale = 0.74569987158227022, default = "kW/t", link = "Power-to-weight ratio", }, ["kW/kg"] = { name1 = "kilowatt per kilogram", name2 = "kilowatts per kilogram", symbol = "kW/kg", utype = "power per unit mass", scale = 1000, default = "hp/lb", link = "Power-to-weight ratio", }, ["kW/t"] = { name1 = "kilowatt per tonne", name2 = "kilowatts per tonne", symbol = "kW/t", utype = "power per unit mass", scale = 1, default = "PS/t", link = "Power-to-weight ratio", }, ["PS/t"] = { name1 = "metric horsepower per tonne", name2 = "metric horsepower per tonne", symbol = "PS/t", utype = "power per unit mass", scale = 0.73549875, default = "kW/t", link = "Power-to-weight ratio", }, ["shp/lb"] = { name1 = "shaft horsepower per pound", name2 = "shaft horsepower per pound", symbol = "shp/lb", utype = "power per unit mass", scale = 1643.986806, default = "kW/kg", link = "Power-to-weight ratio", }, ["hp/tonne"] = { target = "hp/t", symbol = "hp/tonne", default = "kW/tonne", }, ["kW/tonne"] = { target = "kW/t", symbol = "kW/tonne", }, ["-lb/in2"] = { name1 = "pound per square inch", name2 = "pounds per square inch", symbol = "lb/in<sup>2</sup>", utype = "pressure", scale = 6894.7572931683608, default = "kPa kgf/cm2", }, ["atm"] = { name1 = "standard atmosphere", symbol = "atm", utype = "pressure", scale = 101325, default = "kPa", link = "Atmosphere (unit)", }, ["Ba"] = { name1 = "barye", symbol = "Ba", utype = "pressure", scale = 0.1, default = "Pa", }, ["bar"] = { symbol = "bar", utype = "pressure", scale = 100000, default = "kPa", link = "Bar (unit)", }, ["dbar"] = { name1 = "decibar", symbol = "dbar", utype = "pressure", scale = 10000, default = "kPa", link = "Bar (unit)", }, ["inHg"] = { name1 = "inch of mercury", name2 = "inches of mercury", symbol = "inHg", utype = "pressure", scale = 3386.388640341, default = "kPa", }, ["kBa"] = { name1 = "kilobarye", symbol = "kBa", utype = "pressure", scale = 100, default = "hPa", link = "Barye", }, ["kg-f/cm2"] = { name1 = "kilogram-force per square centimetre", name1_us = "kilogram-force per square centimeter", name2 = "kilograms-force per square centimetre", name2_us = "kilograms-force per square centimeter", symbol = "kg<sub>f</sub>/cm<sup>2</sup>", utype = "pressure", scale = 98066.5, default = "psi", link = "Kilogram-force", }, ["kg/cm2"] = { name1 = "kilogram per square centimetre", name1_us = "kilogram per square centimeter", name2 = "kilograms per square centimetre", name2_us = "kilograms per square centimeter", symbol = "kg/cm<sup>2</sup>", utype = "pressure", scale = 98066.5, default = "psi", link = "Kilogram-force", }, ["kgf/cm2"] = { name1 = "kilogram-force per square centimetre", name1_us = "kilogram-force per square centimeter", name2 = "kilograms-force per square centimetre", name2_us = "kilograms-force per square centimeter", symbol = "kgf/cm<sup>2</sup>", utype = "pressure", scale = 98066.5, default = "psi", link = "Kilogram-force", }, ["ksi"] = { name1 = "kilopound per square inch", name2 = "kilopounds per square inch", symbol = "ksi", utype = "pressure", scale = 6894757.2931683613, default = "MPa", link = "Pound per square inch", }, ["lbf/in2"] = { name1 = "pound-force per square inch", name2 = "pounds-force per square inch", symbol = "lbf/in<sup>2</sup>", utype = "pressure", scale = 6894.7572931683608, default = "kPa kgf/cm2", }, ["mb"] = { name1 = "millibar", symbol = "mb", utype = "pressure", scale = 100, default = "hPa", link = "Bar (unit)", }, ["mbar"] = { name1 = "millibar", symbol = "mbar", utype = "pressure", scale = 100, default = "hPa", link = "Bar (unit)", }, ["mmHg"] = { name1 = "millimetre of mercury", name1_us = "millimeter of mercury", name2 = "millimetres of mercury", name2_us = "millimeters of mercury", symbol = "mmHg", utype = "pressure", scale = 133.322387415, default = "kPa", }, ["Pa"] = { _name1 = "pascal", _symbol = "Pa", utype = "pressure", scale = 1, prefixes = 1, default = "psi", link = "Pascal (unit)", }, ["psf"] = { name1 = "pound per square foot", name2 = "pounds per square foot", symbol = "psf", utype = "pressure", scale = 47.880258980335839, default = "kPa", link = "Pound per square inch", }, ["psi"] = { name1 = "pound per square inch", name2 = "pounds per square inch", symbol = "psi", utype = "pressure", scale = 6894.7572931683608, default = "kPa", }, ["Torr"] = { name1 = "torr", symbol = "Torr", utype = "pressure", scale = 133.32236842105263, default = "kPa", }, ["N/cm2"] = { per = { "N", "cm2" }, utype = "pressure", default = "psi", }, ["N/m2"] = { per = { "N", "m2" }, utype = "pressure", default = "psi", }, ["g/cm2"] = { per = { "g", "cm2" }, utype = "pressure", default = "lb/sqft", multiplier= 9.80665, }, ["g/m2"] = { per = { "g", "m2" }, utype = "pressure", default = "lb/sqft", multiplier= 9.80665, }, ["kg/ha"] = { per = { "kg", "ha" }, utype = "pressure", default = "lb/acre", multiplier= 9.80665, }, ["kg/m2"] = { per = { "kg", "m2" }, utype = "pressure", default = "lb/sqft", multiplier= 9.80665, }, ["lb/1000sqft"] = { per = { "lb", "1000sqft" }, utype = "pressure", default = "g/m2", multiplier= 9.80665, }, ["lb/acre"] = { per = { "lb", "acre" }, utype = "pressure", default = "kg/ha", multiplier= 9.80665, }, ["lb/sqft"] = { per = { "lb", "sqft" }, utype = "pressure", default = "kg/m2", multiplier= 9.80665, }, ["lb/sqyd"] = { per = { "lb", "sqyd" }, utype = "pressure", default = "kg/m2", multiplier= 9.80665, }, ["LT/acre"] = { per = { "LT", "acre" }, utype = "pressure", default = "t/ha", multiplier= 9.80665, }, ["MT/ha"] = { per = { "MT", "ha" }, utype = "pressure", default = "LT/acre ST/acre", multiplier= 9.80665, }, ["oz/sqft"] = { per = { "oz", "sqft" }, utype = "pressure", default = "g/m2", multiplier= 9.80665, }, ["oz/sqyd"] = { per = { "oz", "sqyd" }, utype = "pressure", default = "g/m2", multiplier= 9.80665, }, ["ST/acre"] = { per = { "ST", "acre" }, utype = "pressure", default = "t/ha", multiplier= 9.80665, }, ["t/ha"] = { per = { "t", "ha" }, utype = "pressure", default = "LT/acre ST/acre", multiplier= 9.80665, }, ["tonne/acre"] = { per = { "tonne", "acre" }, utype = "pressure", default = "tonne/ha", multiplier= 9.80665, }, ["tonne/ha"] = { per = { "tonne", "ha" }, utype = "pressure", default = "tonne/acre", multiplier= 9.80665, }, ["kgfpsqcm"] = { target = "kgf/cm2", }, ["kgpsqcm"] = { target = "kg/cm2", }, ["kN/m2"] = { target = "kPa", }, ["lb/in2"] = { target = "lbf/in2", }, ["torr"] = { target = "Torr", }, ["Bq"] = { _name1 = "becquerel", _symbol = "Bq", utype = "radioactivity", scale = 1, prefixes = 1, default = "pCi", link = "Becquerel", }, ["Ci"] = { _name1 = "curie", _symbol = "Ci", utype = "radioactivity", scale = 3.7e10, prefixes = 1, default = "GBq", link = "Curie (unit)", }, ["Rd"] = { _name1 = "rutherford", _symbol = "Rd", utype = "radioactivity", scale = 1e6, prefixes = 1, default = "MBq", link = "Rutherford (unit)", }, ["cm/h"] = { name1 = "centimetre per hour", name1_us = "centimeter per hour", name2 = "centimetres per hour", name2_us = "centimeters per hour", symbol = "cm/h", utype = "speed", scale = 2.7777777777777775e-6, default = "in/h", link = "Metre per second", }, ["cm/s"] = { name1 = "centimetre per second", name1_us = "centimeter per second", name2 = "centimetres per second", name2_us = "centimeters per second", symbol = "cm/s", utype = "speed", scale = 0.01, default = "in/s", link = "Metre per second", }, ["cm/year"] = { name1 = "centimetre per year", name1_us = "centimeter per year", name2 = "centimetres per year", name2_us = "centimeters per year", symbol = "cm/year", utype = "speed", scale = 3.168873850681143e-10, default = "in/year", link = "Orders of magnitude (speed)", }, ["foot/s"] = { name1 = "foot per second", name2 = "foot per second", symbol = "ft/s", utype = "speed", scale = 0.3048, default = "m/s", }, ["ft/min"] = { name1 = "foot per minute", name2 = "feet per minute", symbol = "ft/min", utype = "speed", scale = 0.00508, default = "m/min", link = "Feet per second", }, ["ft/s"] = { name1 = "foot per second", name2 = "feet per second", symbol = "ft/s", utype = "speed", scale = 0.3048, default = "m/s", link = "Feet per second", }, ["furlong per fortnight"] = { name2 = "furlongs per fortnight", symbol = "furlong per fortnight", usename = 1, utype = "speed", scale = 0.00016630952380952381, default = "km/h mph", link = "FFF system", }, ["in/h"] = { name1 = "inch per hour", name2 = "inches per hour", symbol = "in/h", utype = "speed", scale = 7.0555555555555559e-6, default = "cm/h", link = "Inch", }, ["in/s"] = { name1 = "inch per second", name2 = "inches per second", symbol = "in/s", utype = "speed", scale = 0.0254, default = "cm/s", link = "Inch", }, ["in/year"] = { name1 = "inch per year", name2 = "inches per year", symbol = "in/year", utype = "speed", scale = 8.0489395807301024e-10, default = "cm/year", link = "Orders of magnitude (speed)", }, ["isp"] = { name1 = "second", symbol = "s", utype = "speed", scale = 9.80665, default = "km/s", link = "Specific impulse", }, ["km/d"] = { name1 = "kilometre per day", name1_us = "kilometer per day", name2 = "kilometres per day", name2_us = "kilometers per day", symbol = "km/d", utype = "speed", scale = 1.1574074074074074e-2, default = "mi/d", link = "Orders of magnitude (speed)", }, ["km/h"] = { name1 = "kilometre per hour", name1_us = "kilometer per hour", name2 = "kilometres per hour", name2_us = "kilometers per hour", symbol = "km/h", utype = "speed", scale = 0.27777777777777779, default = "mph", link = "Kilometres per hour", }, ["km/s"] = { name1 = "kilometre per second", name1_us = "kilometer per second", name2 = "kilometres per second", name2_us = "kilometers per second", symbol = "km/s", utype = "speed", scale = 1000, default = "mi/s", link = "Metre per second", }, ["kn"] = { name1 = "knot", symbol = "kn", utype = "speed", scale = 0.51444444444444448, default = "km/h mph", link = "Knot (unit)", }, ["kNs/kg"] = { name2 = "kN&#8209;s/kg", symbol = "kN&#8209;s/kg", utype = "speed", scale = 1000, default = "isp", link = "Specific impulse", }, ["m/min"] = { name1 = "metre per minute", name1_us = "meter per minute", name2 = "metres per minute", name2_us = "meters per minute", symbol = "m/min", utype = "speed", scale = 0.016666666666666666, default = "ft/min", link = "Metre per second", }, ["m/s"] = { name1 = "metre per second", name1_us = "meter per second", name2 = "metres per second", name2_us = "meters per second", symbol = "m/s", utype = "speed", scale = 1, default = "ft/s", }, ["Mach"] = { name2 = "Mach", symbol = "Mach", utype = "speed", builtin = "mach", scale = 0, iscomplex= true, default = "km/h mph", link = "Mach number", }, ["mi/d"] = { name1 = "mile per day", name2 = "miles per day", symbol = "mi/d", utype = "speed", scale = 1.8626666666666667e-2, default = "km/d", link = "Orders of magnitude (speed)", }, ["mi/s"] = { name1 = "mile per second", name2 = "miles per second", symbol = "mi/s", utype = "speed", scale = 1609.344, default = "km/s", link = "Mile", }, ["mm/h"] = { name1 = "millimetre per hour", name1_us = "millimeter per hour", name2 = "millimetres per hour", name2_us = "millimeters per hour", symbol = "mm/h", utype = "speed", scale = 2.7777777777777781e-7, default = "in/h", link = "Metre per second", }, ["mph"] = { name1 = "mile per hour", name2 = "miles per hour", symbol = "mph", utype = "speed", scale = 0.44704, default = "km/h", link = "Miles per hour", }, ["Ns/kg"] = { name2 = "N&#8209;s/kg", symbol = "N&#8209;s/kg", utype = "speed", scale = 1, default = "isp", link = "Specific impulse", }, ["si tsfc"] = { name2 = "g/(kN⋅s)", symbol = "g/(kN⋅s)", utype = "speed", scale = 9.9999628621379242e-7, invert = -1, iscomplex= true, default = "tsfc", link = "Thrust specific fuel consumption", }, ["tsfc"] = { name2 = "lb/(lbf⋅h)", symbol = "lb/(lbf⋅h)", utype = "speed", scale = 2.832545036049801e-5, invert = -1, iscomplex= true, default = "si tsfc", link = "Thrust specific fuel consumption", }, ["cm/y"] = { target = "cm/year", }, ["cm/yr"] = { target = "cm/year", }, ["in/y"] = { target = "in/year", }, ["in/yr"] = { target = "in/year", }, ["knot"] = { target = "kn", }, ["knots"] = { target = "kn", }, ["kph"] = { target = "km/h", }, ["mi/h"] = { target = "mph", }, ["mm/s"] = { per = { "mm", "s" }, utype = "speed", default = "in/s", link = "Metre per second", }, ["C"] = { name1 = "degree Celsius", name2 = "degrees Celsius", symbol = "°C", usesymbol= 1, utype = "temperature", scale = 1, offset = -273.15, iscomplex= true, istemperature= true, default = "F", link = "Celsius", }, ["F"] = { name1 = "degree Fahrenheit", name2 = "degrees Fahrenheit", symbol = "°F", usesymbol= 1, utype = "temperature", scale = 0.55555555555555558, offset = 32-273.15*(9/5), iscomplex= true, istemperature= true, default = "C", link = "Fahrenheit", }, ["K"] = { _name1 = "kelvin", _symbol = "K", usesymbol= 1, utype = "temperature", scale = 1, offset = 0, iscomplex= true, istemperature= true, prefixes = 1, default = "C F", link = "Kelvin", }, ["keVT"] = { name1 = "kiloelectronvolt", symbol = "keV", utype = "temperature", scale = 11.604505e6, offset = 0, iscomplex= true, default = "MK", link = "Electronvolt", }, ["R"] = { name1 = "degree Rankine", name2 = "degrees Rankine", symbol = "°R", usesymbol= 1, utype = "temperature", scale = 0.55555555555555558, offset = 0, iscomplex= true, istemperature= true, default = "K F C", link = "Rankine scale", }, ["Celsius"] = { target = "C", }, ["°C"] = { target = "C", }, ["°F"] = { target = "F", }, ["°R"] = { target = "R", }, ["C-change"] = { name1 = "degree Celsius change", name2 = "degrees Celsius change", symbol = "°C", usesymbol= 1, utype = "temperature change", scale = 1, default = "F-change", link = "Celsius", }, ["F-change"] = { name1 = "degree Fahrenheit change", name2 = "degrees Fahrenheit change", symbol = "°F", usesymbol= 1, utype = "temperature change", scale = 0.55555555555555558, default = "C-change", link = "Fahrenheit", }, ["K-change"] = { name1 = "kelvin change", name2 = "kelvins change", symbol = "K", usesymbol= 1, utype = "temperature change", scale = 1, default = "F-change", link = "Kelvin", }, ["°C-change"] = { target = "C-change", }, ["°F-change"] = { target = "F-change", }, ["century"] = { name1 = "century", name2 = "centuries", symbol = "ha", utype = "time", scale = 3155760000, default = "Gs", }, ["d"] = { name1 = "day", symbol = "d", utype = "time", scale = 86400, default = "ks", }, ["decade"] = { name1 = "decade", symbol = "daa", utype = "time", scale = 315576000, default = "Ms", }, ["dog year"] = { name1 = "dog year", symbol = "dog yr", utype = "time", scale = 220903200, default = "years", link = "List of unusual units of measurement#Dog year", }, ["fortnight"] = { symbol = "fortnight", usename = 1, utype = "time", scale = 1209600, default = "week", }, ["h"] = { name1 = "hour", symbol = "h", utype = "time", scale = 3600, default = "ks", }, ["long billion year"] = { name1 = "billion years", name2 = "billion years", symbol = "Ta", utype = "time", scale = 31557600000000000000, default = "Es", link = "Annum", }, ["millennium"] = { name1 = "millennium", name2 = "millennia", symbol = "ka", utype = "time", scale = 31557600000, default = "Gs", }, ["milliard year"] = { name1 = "milliard years", name2 = "milliard years", symbol = "Ga", utype = "time", scale = 31557600000000000, default = "Ps", link = "Annum", }, ["million year"] = { name1 = "million years", name2 = "million years", symbol = "Ma", utype = "time", scale = 31557600000000, default = "Ts", link = "Annum", }, ["min"] = { name1 = "minute", symbol = "min", utype = "time", scale = 60, default = "s", }, ["month"] = { symbol = "month", usename = 1, utype = "time", scale = 2629800, default = "Ms", }, ["months"] = { name1 = "month", symbol = "mo", utype = "time", scale = 2629800, default = "year", }, ["s"] = { _name1 = "second", _symbol = "s", utype = "time", scale = 1, prefixes = 1, default = "min", link = "Second", }, ["short billion year"] = { name1 = "billion years", name2 = "billion years", symbol = "Ga", utype = "time", scale = 31557600000000000, default = "Ps", link = "Annum", }, ["short trillion year"] = { name1 = "trillion years", name2 = "trillion years", symbol = "Ta", utype = "time", scale = 31557600000000000000, default = "Es", link = "Annum", }, ["thousand million year"] = { name1 = "thousand million years", name2 = "thousand million years", symbol = "Ga", utype = "time", scale = 31557600000000000, default = "Ps", link = "Annum", }, ["wk"] = { symbol = "week", usename = 1, utype = "time", scale = 604800, default = "Ms", }, ["year"] = { name1 = "year", symbol = "a", utype = "time", scale = 31557600, default = "Ms", link = "Annum", }, ["years"] = { name1 = "year", symbol = "yr", utype = "time", scale = 31557600, default = "Ms", link = "Annum", }, ["byr"] = { target = "short billion year", }, ["day"] = { target = "d", }, ["days"] = { target = "d", }, ["dog yr"] = { target = "dog year", }, ["Gyr"] = { target = "thousand million year", }, ["hour"] = { target = "h", }, ["hours"] = { target = "h", }, ["kMyr"] = { target = "thousand million year", }, ["kmyr"] = { target = "thousand million year", }, ["kyr"] = { target = "millennium", }, ["long byr"] = { target = "long billion year", }, ["minute"] = { target = "min", }, ["minutes"] = { target = "min", }, ["mth"] = { target = "month", }, ["Myr"] = { target = "million year", }, ["myr"] = { target = "million year", }, ["second"] = { target = "s", }, ["seconds"] = { target = "s", }, ["tmyr"] = { target = "thousand million year", }, ["tryr"] = { target = "short trillion year", }, ["tyr"] = { target = "millennium", }, ["week"] = { target = "wk", }, ["weeks"] = { target = "wk", }, ["yr"] = { target = "year", }, ["kg.m"] = { name1 = "kilogram metre", name1_us = "kilogram meter", symbol = "kg⋅m", utype = "torque", scale = 9.80665, default = "Nm lbft", link = "Kilogram metre (torque)", }, ["kgf.m"] = { name1 = "kilogram force-metre", name1_us = "kilogram force-meter", symbol = "kgf⋅m", utype = "torque", scale = 9.80665, default = "Nm lbfft", link = "Kilogram metre (torque)", }, ["kgm"] = { name1 = "kilogram metre", name1_us = "kilogram meter", symbol = "kg⋅m", utype = "torque", scale = 9.80665, default = "Nm lbfft", link = "Kilogram metre (torque)", }, ["kpm"] = { name1 = "kilopond metre", name1_us = "kilopond meter", symbol = "kp⋅m", utype = "torque", scale = 9.80665, default = "Nm lbft", link = "Kilogram metre (torque)", }, ["lb-fft"] = { name1 = "pound force-foot", name2 = "pound force-feet", symbol = "ft⋅lb<sub>f</sub>", utype = "torque", scale = 1.3558179483314004, default = "Nm", link = "Pound-foot (torque)", }, ["lb.ft"] = { name1 = "pound force-foot", name2 = "pound force-feet", symbol = "lb⋅ft", utype = "torque", scale = 1.3558179483314004, default = "Nm", link = "Pound-foot (torque)", }, ["lb.in"] = { name1 = "pound force-inch", symbol = "lb⋅in", utype = "torque", scale = 0.1129848290276167, default = "mN.m", link = "Pound-foot (torque)", }, ["lbfft"] = { name1 = "pound force-foot", name2 = "pound force-feet", symbol = "lbf⋅ft", utype = "torque", scale = 1.3558179483314004, default = "Nm", link = "Pound-foot (torque)", }, ["lbft"] = { name1 = "pound-foot", name2 = "pound-feet", symbol = "lb⋅ft", utype = "torque", scale = 1.3558179483314004, default = "Nm", link = "Pound-foot (torque)", }, ["m.kg-f"] = { name1 = "metre kilogram-force", name1_us = "meter kilogram-force", name2 = "metre kilograms-force", name2_us = "meter kilograms-force", symbol = "m⋅kg<sub>f</sub>", utype = "torque", scale = 9.80665, default = "Nm lbfft", link = "Kilogram metre (torque)", }, ["m.kgf"] = { name1 = "metre kilogram-force", name1_us = "meter kilogram-force", name2 = "metre kilograms-force", name2_us = "meter kilograms-force", symbol = "m⋅kgf", utype = "torque", scale = 9.80665, default = "Nm lbfft", link = "Kilogram metre (torque)", }, ["mN.m"] = { name1 = "millinewton-metre", name1_us = "millinewton-meter", symbol = "mN⋅m", utype = "torque", scale = 0.001, default = "lb.in", link = "Newton-metre", }, ["Nm"] = { _name1 = "newton-metre", _name1_us= "newton-meter", _symbol = "N⋅m", utype = "torque", alttype = "energy", scale = 1, prefixes = 1, default = "lbfft", link = "Newton-metre", }, ["kN/m"] = { per = { "kN", "-m-stiff" }, utype = "torque", default = "lbf/in", }, ["lbf/in"] = { per = { "lbf", "-in-stiff" }, utype = "torque", default = "kN/m", }, ["lb-f.ft"] = { target = "lb-fft", }, ["lbf.ft"] = { target = "lbfft", }, ["lbf·ft"] = { target = "lbfft", }, ["lb·ft"] = { target = "lb.ft", }, ["mkg-f"] = { target = "m.kg-f", }, ["mkgf"] = { target = "m.kgf", }, ["N.m"] = { target = "Nm", }, ["N·m"] = { target = "Nm", }, ["ton-mile"] = { symbol = "ton-mile", usename = 1, utype = "transportation", scale = 1.4599723182105602, default = "tkm", }, ["tkm"] = { name1 = "tonne-kilometre", name1_us = "tonne-kilometer", symbol = "tkm", utype = "transportation", scale = 1, default = "ton-mile", }, ["-12USoz(mL)serve"] = { name1_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz (355&nbsp;mL) serving", symbol = "12&nbsp;US&nbsp;fl&nbsp;oz (355&nbsp;mL) serving", sym_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz (355&nbsp;mL) serving", utype = "volume", scale = 0.00035488235475000004, default = "mL", link = "Beverage can#Standard sizes", }, ["-12USoz(ml)serve"] = { name1_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz (355&nbsp;ml) serving", symbol = "12&nbsp;US&nbsp;fl&nbsp;oz (355&nbsp;ml) serving", sym_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz (355&nbsp;ml) serving", utype = "volume", scale = 0.00035488235475000004, default = "ml", link = "Beverage can#Standard sizes", }, ["-12USozserve"] = { name1_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz serving", symbol = "12&nbsp;US&nbsp;fl&nbsp;oz serving", sym_us = "12&nbsp;U.S.&nbsp;fl&nbsp;oz serving", utype = "volume", scale = 0.00035488235475000004, default = "mL", link = "Beverage can#Standard sizes", }, ["acre-foot"] = { name1 = "acre-foot", name2 = "acre-foot", symbol = "acre⋅ft", utype = "volume", scale = 1233.48183754752, default = "m3", }, ["acre-ft"] = { name1 = "acre-foot", name2 = "acre-feet", symbol = "acre⋅ft", utype = "volume", scale = 1233.48183754752, default = "m3", }, ["AUtbsp"] = { name1 = "Australian tablespoon", symbol = "AU&nbsp;tbsp", utype = "volume", scale = 0.000020, default = "ml", }, ["Bcuft"] = { name1 = "billion cubic foot", name2 = "billion cubic feet", symbol = "billion cu&nbsp;ft", utype = "volume", scale = 28316846.592, default = "Gl", link = "Cubic foot", }, ["bdft"] = { name1 = "board foot", name2 = "board feet", symbol = "bd&nbsp;ft", utype = "volume", scale = 0.0023597372167, default = "m3", }, ["board feet"] = { name2 = "board feet", symbol = "board foot", usename = 1, utype = "volume", scale = 0.0023597372167, default = "m3", }, ["board foot"] = { name2 = "board foot", symbol = "board foot", usename = 1, utype = "volume", scale = 0.0023597372167, default = "m3", }, ["cc"] = { name1 = "cubic centimetre", name1_us = "cubic centimeter", symbol = "cc", utype = "volume", scale = 0.000001, default = "cuin", }, ["CID"] = { name1 = "cubic inch", name2 = "cubic inches", symbol = "cu&nbsp;in", utype = "volume", scale = 0.000016387064, default = "cc", link = "Cubic inch#Engine displacement", }, ["cord"] = { symbol = "cord", utype = "volume", scale = 3.624556363776, default = "m3", link = "Cord (unit)", }, ["cufoot"] = { name1 = "cubic foot", name2 = "cubic foot", symbol = "cu&nbsp;ft", utype = "volume", scale = 0.028316846592, default = "m3", }, ["cuft"] = { name1 = "cubic foot", name2 = "cubic feet", symbol = "cu&nbsp;ft", utype = "volume", scale = 0.028316846592, default = "m3", }, ["cuin"] = { name1 = "cubic inch", name2 = "cubic inches", symbol = "cu&nbsp;in", utype = "volume", scale = 0.000016387064, default = "cm3", }, ["cumi"] = { name1 = "cubic mile", symbol = "cu&nbsp;mi", utype = "volume", scale = 4168181825.440579584, default = "km3", }, ["cuyd"] = { name1 = "cubic yard", symbol = "cu&nbsp;yd", utype = "volume", scale = 0.764554857984, default = "m3", }, ["firkin"] = { symbol = "firkin", usename = 1, utype = "volume", scale = 0.04091481, default = "l impgal USgal", link = "Firkin (unit)", }, ["foot3"] = { target = "cufoot", }, ["Goilbbl"] = { name1 = "billion barrels", name2 = "billion barrels", symbol = "Gbbl", utype = "volume", scale = 158987294.928, default = "v * 1.58987294928 < 10 ! e6 ! e9 ! m3", link = "Barrel (unit)#Oil barrel", }, ["gr water"] = { name1 = "grains water", name2 = "grains water", symbol = "gr H<sub>2</sub>O", utype = "volume", scale = 0.00000006479891, default = "cm3", link = "Grain (unit)", }, ["grt"] = { name1 = "gross register ton", symbol = "grt", utype = "volume", scale = 2.8316846592, default = "m3", link = "Gross register tonnage", }, ["impbbl"] = { name1 = "imperial barrel", symbol = "imp&nbsp;bbl", utype = "volume", scale = 0.16365924, default = "l impgal USgal", link = "Barrel (unit)", }, ["impbsh"] = { name1 = "imperial bushel", symbol = "imp&nbsp;bsh", utype = "volume", scale = 0.03636872, default = "l impgal USdrygal", }, ["impbu"] = { name1 = "imperial bushel", symbol = "imp&nbsp;bu", utype = "volume", scale = 0.03636872, default = "m3", }, ["impgal"] = { name1 = "imperial gallon", symbol = "imp&nbsp;gal", utype = "volume", scale = 0.00454609, default = "l USgal", }, ["impgi"] = { name1 = "gill", symbol = "gi", utype = "volume", scale = 0.0001420653125, default = "ml USoz", link = "Gill (unit)", }, ["impkenning"] = { name1 = "imperial kenning", symbol = "kenning", utype = "volume", scale = 0.01818436, default = "l USdrygal", link = "Kenning (unit)", }, ["impoz"] = { name1 = "imperial fluid ounce", symbol = "imp&nbsp;fl&nbsp;oz", utype = "volume", scale = 0.0000284130625, default = "ml USoz", }, ["imppk"] = { name1 = "imperial peck", symbol = "pk", utype = "volume", scale = 0.00909218, default = "l USdrygal", link = "Peck", }, ["imppt"] = { name1 = "imperial pint", symbol = "imp&nbsp;pt", utype = "volume", scale = 0.00056826125, default = "l", }, ["impqt"] = { name1 = "imperial quart", symbol = "imp&nbsp;qt", utype = "volume", scale = 0.0011365225, default = "ml USoz", customary= 3, }, ["kilderkin"] = { symbol = "kilderkin", usename = 1, utype = "volume", scale = 0.08182962, default = "l impgal USgal", }, ["koilbbl"] = { name1 = "thousand barrels", name2 = "thousand barrels", symbol = "kbbl", utype = "volume", scale = 158.987294928, default = "v * 1.58987294928 < 10 ! ! e3 ! m3", link = "Barrel (unit)#Oil barrel", }, ["L"] = { _name1 = "litre", _name1_us= "liter", _symbol = "L", utype = "volume", scale = 0.001, prefixes = 1, default = "impgal USgal", link = "Litre", }, ["l"] = { _name1 = "litre", _name1_us= "liter", _symbol = "l", utype = "volume", scale = 0.001, prefixes = 1, default = "impgal USgal", link = "Litre", }, ["m3"] = { _name1 = "cubic metre", _name1_us= "cubic meter", _symbol = "m<sup>3</sup>", prefix_position= 7, utype = "volume", scale = 1, prefixes = 3, default = "cuft", link = "Cubic metre", }, ["Mbbl"] = { name1 = "thousand barrels", name2 = "thousand barrels", symbol = "Mbbl", utype = "volume", scale = 158.987294928, default = "v * 1.58987294928 < 10 ! e3 ! ! m3", link = "Barrel (unit)#Oil barrel", }, ["MMoilbbl"] = { name1 = "million barrels", name2 = "million barrels", symbol = "MMbbl", utype = "volume", scale = 158987.294928, default = "v * 1.58987294928 < 10 ! e3 ! e6 ! m3", link = "Barrel (unit)#Oil barrel", }, ["Moilbbl"] = { name1 = "million barrels", name2 = "million barrels", symbol = "Mbbl", utype = "volume", scale = 158987.294928, default = "v * 1.58987294928 < 10 ! e3 ! e6 ! m3", link = "Barrel (unit)#Oil barrel", }, ["MTON"] = { name1 = "measurement ton", symbol = "MTON", utype = "volume", scale = 1.13267386368, default = "m3", }, ["MUSgal"] = { name1 = "million US gallons", name1_us = "million U.S. gallons", name2 = "million US gallons", name2_us = "million U.S. gallons", symbol = "million US&nbsp;gal", sym_us = "million U.S.&nbsp;gal", utype = "volume", scale = 3785.411784, default = "Ml", link = "US gallon", }, ["oilbbl"] = { name1 = "barrel", symbol = "bbl", utype = "volume", scale = 0.158987294928, default = "m3", link = "Barrel (unit)#Oil barrel", }, ["stere"] = { symbol = "stere", usename = 1, utype = "volume", scale = 1, default = "cuft", }, ["Toilbbl"] = { name1 = "trillion barrels", name2 = "trillion barrels", symbol = "Tbbl", utype = "volume", scale = 158987294928, default = "v * 1.58987294928 < 10 ! e9 ! e12 ! m3", link = "Barrel (unit)#Oil barrel", }, ["USbbl"] = { name1 = "US barrel", name1_us = "U.S. barrel", symbol = "US&nbsp;bbl", sym_us = "U.S.&nbsp;bbl", utype = "volume", scale = 0.119240471196, default = "l USgal impgal", link = "Barrel (unit)", }, ["USbeerbbl"] = { name1 = "US beer barrel", name1_us = "U.S. beer barrel", symbol = "US&nbsp;bbl", sym_us = "U.S.&nbsp;bbl", utype = "volume", scale = 0.117347765304, default = "l USgal impgal", link = "Barrel (unit)", }, ["USbsh"] = { name1 = "US bushel", name1_us = "U.S. bushel", symbol = "US&nbsp;bsh", sym_us = "U.S.&nbsp;bsh", utype = "volume", scale = 0.03523907016688, default = "l USdrygal impgal", link = "Bushel", }, ["USbu"] = { name1 = "US bushel", name1_us = "U.S. bushel", symbol = "US&nbsp;bu", sym_us = "U.S.&nbsp;bu", utype = "volume", scale = 0.03523907016688, default = "l USdrygal impgal", link = "Bushel", }, ["USdrybbl"] = { name1 = "US dry barrel", name1_us = "U.S. dry barrel", symbol = "US&nbsp;dry&nbsp;bbl", sym_us = "U.S.&nbsp;dry&nbsp;bbl", utype = "volume", scale = 0.11562819898508, default = "m3", link = "Barrel (unit)", }, ["USdrygal"] = { name1 = "US dry gallon", name1_us = "U.S. dry gallon", symbol = "US&nbsp;dry&nbsp;gal", sym_us = "U.S.&nbsp;dry&nbsp;gal", utype = "volume", scale = 0.00440488377086, default = "l", link = "Gallon", }, ["USdrypt"] = { name1 = "US dry pint", name1_us = "U.S. dry pint", symbol = "US&nbsp;dry&nbsp;pt", sym_us = "U.S.&nbsp;dry&nbsp;pt", utype = "volume", scale = 0.0005506104713575, default = "ml", link = "Pint", }, ["USdryqt"] = { name1 = "US dry quart", name1_us = "U.S. dry quart", symbol = "US&nbsp;dry&nbsp;qt", sym_us = "U.S.&nbsp;dry&nbsp;qt", utype = "volume", scale = 0.001101220942715, default = "ml", link = "Quart", }, ["USflgal"] = { name1 = "US gallon", name1_us = "U.S. gallon", symbol = "US fl gal", sym_us = "U.S.&nbsp;fl&nbsp;gal", utype = "volume", scale = 0.003785411784, default = "l impgal", link = "Gallon", }, ["USgal"] = { name1 = "US gallon", name1_us = "U.S. gallon", symbol = "US&nbsp;gal", sym_us = "U.S.&nbsp;gal", utype = "volume", scale = 0.003785411784, default = "l impgal", }, ["USgi"] = { name1 = "gill", symbol = "gi", utype = "volume", scale = 0.0001182941183, default = "ml impoz", link = "Gill (unit)", }, ["USkenning"] = { name1 = "US kenning", name1_us = "U.S. kenning", symbol = "US&nbsp;kenning", sym_us = "U.S.&nbsp;kenning", utype = "volume", scale = 0.01761953508344, default = "l impgal", link = "Kenning (unit)", }, ["USmin"] = { name1 = "US minim", name1_us = "U.S. minim", symbol = "US&nbsp;min", sym_us = "U.S.&nbsp;min", utype = "volume", scale = 0.000000061611519921875, default = "ml", link = "Minim (unit)", }, ["USoz"] = { name1 = "US fluid ounce", name1_us = "U.S. fluid ounce", symbol = "US&nbsp;fl&nbsp;oz", sym_us = "U.S.&nbsp;fl&nbsp;oz", utype = "volume", scale = 0.0000295735295625, default = "ml", }, ["USpk"] = { name1 = "US peck", name1_us = "U.S. peck", symbol = "US&nbsp;pk", sym_us = "U.S.&nbsp;pk", utype = "volume", scale = 0.00880976754172, default = "l impgal", link = "Peck", }, ["USpt"] = { name1 = "US pint", name1_us = "U.S. pint", symbol = "US&nbsp;pt", sym_us = "U.S.&nbsp;pt", utype = "volume", scale = 0.000473176473, default = "l imppt", link = "Pint", }, ["USqt"] = { name1 = "US quart", name1_us = "U.S. quart", symbol = "US&nbsp;qt", sym_us = "U.S.&nbsp;qt", utype = "volume", scale = 0.000946352946, default = "ml", link = "Quart", customary= 1, }, ["USquart"] = { name1 = "US quart", name1_us = "U.S. quart", symbol = "US&nbsp;qt", sym_us = "U.S.&nbsp;qt", utype = "volume", scale = 0.000946352946, default = "ml impoz", link = "Quart", }, ["UStbsp"] = { name1 = "US tablespoon", name1_us = "U.S. tablespoon", symbol = "US&nbsp;tbsp", sym_us = "U.S.&nbsp;tbsp", utype = "volume", scale = 1.4786764781250001e-5, default = "ml", }, ["winecase"] = { symbol = "case", usename = 1, utype = "volume", scale = 0.009, default = "l", link = "Case (goods)", }, ["*U.S.drygal"] = { target = "USdrygal", sp_us = true, customary= 2, }, ["*U.S.gal"] = { target = "USgal", sp_us = true, default = "L impgal", customary= 2, }, ["+USdrygal"] = { target = "USdrygal", customary= 1, }, ["+usfloz"] = { target = "USoz", link = "Fluid ounce", customary= 1, }, ["+USgal"] = { target = "USgal", customary= 1, }, ["+USoz"] = { target = "USoz", customary= 1, }, ["@impgal"] = { target = "impgal", link = "Gallon", customary= 3, }, ["acre feet"] = { target = "acre-ft", }, ["acre foot"] = { target = "acre-foot", }, ["acre ft"] = { target = "acre-ft", }, ["acre-feet"] = { target = "acre-ft", }, ["acre.foot"] = { target = "acre-foot", }, ["acre.ft"] = { target = "acre-ft", }, ["acre·ft"] = { target = "acre-ft", }, ["bushels"] = { target = "USbsh", }, ["cid"] = { target = "CID", }, ["ft3"] = { target = "cuft", }, ["gal"] = { target = "USgal", }, ["gallon"] = { shouldbe = "Use %{USgal%} for US gallons or %{impgal%} for imperial gallons (not %{gallon%})", }, ["gallons"] = { shouldbe = "Use %{USgal%} for US gallons or %{impgal%} for imperial gallons (not %{gallons%})", }, ["Gcuft"] = { target = "e9cuft", }, ["impfloz"] = { target = "impoz", }, ["Impgal"] = { target = "impgal", }, ["in3"] = { target = "cuin", symbol = "in<sup>3</sup>", }, ["kcuft"] = { target = "e3cuft", }, ["kcum"] = { target = "e3m3", }, ["km³"] = { target = "km3", }, ["liter"] = { target = "L", sp_us = true, }, ["liters"] = { target = "L", sp_us = true, }, ["litre"] = { target = "L", }, ["litres"] = { target = "L", }, ["Mcuft"] = { target = "e6cuft", }, ["Mcum"] = { target = "e6m3", }, ["Mft3"] = { target = "e6cuft", }, ["mi3"] = { target = "cumi", }, ["m³"] = { target = "m3", }, ["Pcuft"] = { target = "e15cuft", }, ["pt"] = { shouldbe = "Use %{USpt%} for US pints or %{imppt%} for imperial pints (not %{pt%})", }, ["qt"] = { shouldbe = "Use %{USqt%} for US quarts or %{impqt%} for imperial quarts (not %{qt%})", }, ["Tcuft"] = { target = "e12cuft", }, ["Tft3"] = { target = "e12cuft", }, ["U.S.bbl"] = { target = "USbbl", sp_us = true, default = "l U.S.gal impgal", }, ["U.S.beerbbl"] = { target = "USbeerbbl", sp_us = true, default = "l U.S.gal impgal", }, ["U.S.bsh"] = { target = "USbsh", sp_us = true, default = "l U.S.drygal impgal", }, ["U.S.bu"] = { target = "USbu", sp_us = true, default = "l U.S.drygal impgal", }, ["U.S.drybbl"] = { target = "USdrybbl", sp_us = true, }, ["U.S.drygal"] = { target = "USdrygal", sp_us = true, }, ["U.S.drypt"] = { target = "USdrypt", sp_us = true, }, ["U.S.dryqt"] = { target = "USdryqt", sp_us = true, }, ["U.S.flgal"] = { target = "USflgal", sp_us = true, }, ["U.S.floz"] = { target = "USoz", sp_us = true, }, ["U.S.gal"] = { target = "USgal", sp_us = true, default = "L impgal", link = "U.S. gallon", }, ["u.s.gal"] = { target = "USgal", sp_us = true, default = "L impgal", link = "U.S. gallon", }, ["U.S.gi"] = { target = "USgi", sp_us = true, }, ["U.S.kenning"] = { target = "USkenning", sp_us = true, }, ["U.S.oz"] = { target = "USoz", sp_us = true, }, ["U.S.pk"] = { target = "USpk", sp_us = true, }, ["U.S.pt"] = { target = "USpt", sp_us = true, }, ["U.S.qt"] = { target = "USqt", sp_us = true, default = "L impqt", customary= 2, }, ["usbbl"] = { target = "USbbl", }, ["usbeerbbl"] = { target = "USbeerbbl", }, ["usbsh"] = { target = "USbsh", }, ["usbu"] = { target = "USbu", }, ["usdrybbl"] = { target = "USdrybbl", }, ["usdrygal"] = { target = "USdrygal", }, ["usdrypt"] = { target = "USdrypt", }, ["usdryqt"] = { target = "USdryqt", }, ["USfloz"] = { target = "USoz", }, ["usfloz"] = { target = "USoz", }, ["USGAL"] = { target = "USgal", }, ["usgal"] = { target = "USgal", }, ["usgi"] = { target = "USgi", }, ["uskenning"] = { target = "USkenning", }, ["usoz"] = { target = "USoz", }, ["uspk"] = { target = "USpk", }, ["uspt"] = { target = "USpt", }, ["usqt"] = { target = "USqt", }, ["yd3"] = { target = "cuyd", }, ["cuft/sqmi"] = { per = { "cuft", "sqmi" }, utype = "volume per unit area", default = "m3/km2", }, ["m3/ha"] = { name1 = "cubic metre per hectare", name1_us = "cubic meter per hectare", name2 = "cubic metres per hectare", name2_us = "cubic meters per hectare", symbol = "m<sup>3</sup>/ha", utype = "volume per unit area", scale = 0.0001, default = "USbu/acre", link = "Hectare", }, ["m3/km2"] = { per = { "m3", "km2" }, utype = "volume per unit area", default = "cuft/sqmi", }, ["U.S.gal/acre"] = { per = { "U.S.gal", "acre" }, utype = "volume per unit area", default = "m3/km2", }, ["USbu/acre"] = { name2 = "US bushels per acre", symbol = "US bushel per acre", usename = 1, utype = "volume per unit area", scale = 8.7077638761350888e-6, default = "m3/ha", link = "Bushel", }, ["USgal/acre"] = { per = { "USgal", "acre" }, utype = "volume per unit area", default = "m3/km2", }, ["cuyd/mi"] = { per = { "cuyd", "mi" }, utype = "volume per unit length", default = "m3/km", }, ["m3/km"] = { per = { "m3", "km" }, utype = "volume per unit length", default = "cuyd/mi", }, ["mich"] = { combination= { "ch", "mi" }, multiple = { 80 }, utype = "length", }, ["michlk"] = { combination= { "chlk", "mi" }, multiple = { 80 }, utype = "length", }, ["michainlk"] = { combination= { "chainlk", "mi" }, multiple = { 80 }, utype = "length", }, ["miyd"] = { combination= { "yd", "mi" }, multiple = { 1760 }, utype = "length", }, ["miydftin"] = { combination= { "in", "ft", "yd", "mi" }, multiple = { 12, 3, 1760 }, utype = "length", }, ["mift"] = { combination= { "ft", "mi" }, multiple = { 5280 }, utype = "length", }, ["ydftin"] = { combination= { "in", "ft", "yd" }, multiple = { 12, 3 }, utype = "length", }, ["ydft"] = { combination= { "ft", "yd" }, multiple = { 3 }, utype = "length", }, ["ftin"] = { combination= { "in", "ft" }, multiple = { 12 }, utype = "length", }, ["footin"] = { combination= { "in", "foot" }, multiple = { 12 }, utype = "length", }, ["handin"] = { combination= { "in", "hand" }, multiple = { 4 }, utype = "length", }, ["lboz"] = { combination= { "oz", "lb" }, multiple = { 16 }, utype = "mass", }, ["stlb"] = { combination= { "lb", "st" }, multiple = { 14 }, utype = "mass", }, ["stlboz"] = { combination= { "oz", "lb", "st" }, multiple = { 16, 14 }, utype = "mass", }, ["st and lb"] = { combination= { "lb", "st" }, multiple = { 14 }, utype = "mass", }, ["GN LTf"] = { combination= { "GN", "-LTf" }, utype = "force", }, ["GN LTf STf"] = { combination= { "GN", "-LTf", "-STf" }, utype = "force", }, ["GN STf"] = { combination= { "GN", "-STf" }, utype = "force", }, ["GN STf LTf"] = { combination= { "GN", "-STf", "-LTf" }, utype = "force", }, ["kN LTf"] = { combination= { "kN", "-LTf" }, utype = "force", }, ["kN LTf STf"] = { combination= { "kN", "-LTf", "-STf" }, utype = "force", }, ["kN STf"] = { combination= { "kN", "-STf" }, utype = "force", }, ["kN STf LTf"] = { combination= { "kN", "-STf", "-LTf" }, utype = "force", }, ["LTf STf"] = { combination= { "-LTf", "-STf" }, utype = "force", }, ["MN LTf"] = { combination= { "MN", "-LTf" }, utype = "force", }, ["MN LTf STf"] = { combination= { "MN", "-LTf", "-STf" }, utype = "force", }, ["MN STf"] = { combination= { "MN", "-STf" }, utype = "force", }, ["MN STf LTf"] = { combination= { "MN", "-STf", "-LTf" }, utype = "force", }, ["STf LTf"] = { combination= { "-STf", "-LTf" }, utype = "force", }, ["L/100 km mpgimp"] = { combination= { "L/100 km", "mpgimp" }, utype = "fuel efficiency", }, ["l/100 km mpgimp"] = { combination= { "l/100 km", "mpgimp" }, utype = "fuel efficiency", }, ["L/100 km mpgUS"] = { combination= { "L/100 km", "mpgus" }, utype = "fuel efficiency", }, ["L/100 km mpgus"] = { combination= { "L/100 km", "mpgus" }, utype = "fuel efficiency", }, ["l/100 km mpgus"] = { combination= { "l/100 km", "mpgus" }, utype = "fuel efficiency", }, ["mpgimp L/100 km"] = { combination= { "mpgimp", "L/100 km" }, utype = "fuel efficiency", }, ["LT ST t"] = { combination= { "lt", "-ST", "t" }, utype = "mass", }, ["LT t ST"] = { combination= { "lt", "t", "-ST" }, utype = "mass", }, ["ST LT t"] = { combination= { "-ST", "lt", "t" }, utype = "mass", }, ["ST t LT"] = { combination= { "-ST", "t", "lt" }, utype = "mass", }, ["t LT ST"] = { combination= { "t", "lt", "-ST" }, utype = "mass", }, ["ton"] = { combination= { "LT", "ST" }, utype = "mass", }, ["kPa kg/cm2"] = { combination= { "kPa", "kgf/cm2" }, utype = "pressure", }, ["kPa lb/in2"] = { combination= { "kPa", "-lb/in2" }, utype = "pressure", }, ["floz"] = { combination= { "impoz", "USoz" }, utype = "volume", }, } --------------------------------------------------------------------------- -- Do not change the data in this table because it is created by running -- -- a script that reads the wikitext from a wiki page (see note above). -- --------------------------------------------------------------------------- local default_exceptions = { -- Prefixed units with a default different from that of the base unit. -- Each key item is a prefixed symbol (unitcode for engineering notation). ["cm<sup>2</sup>"] = "sqin", ["dm<sup>2</sup>"] = "sqin", ["e3acre"] = "km2", ["e3m2"] = "e6sqft", ["e6acre"] = "km2", ["e6ha"] = "e6acre", ["e6km2"] = "e6sqmi", ["e6m2"] = "e6sqft", ["e6sqft"] = "v * 9.290304 < 100 ! e3 ! e6 ! m2", ["e6sqmi"] = "e6km2", ["hm<sup>2</sup>"] = "acre", ["km<sup>2</sup>"] = "sqmi", ["mm<sup>2</sup>"] = "sqin", ["aJ"] = "eV", ["e3BTU"] = "MJ", ["e6BTU"] = "GJ", ["EJ"] = "kWh", ["fJ"] = "keV", ["GJ"] = "kWh", ["MJ"] = "kWh", ["PJ"] = "kWh", ["pJ"] = "MeV", ["TJ"] = "kWh", ["YJ"] = "kWh", ["yJ"] = "μeV", ["ZJ"] = "kWh", ["zJ"] = "meV", ["e12cuft/a"] = "v * 2.8316846592 < 100 ! e9 ! e12 ! m3/a", ["e12cuft/d"] = "v * 2.8316846592 < 100 ! e9 ! e12 ! m3/d", ["e12m3/a"] = "Tcuft/a", ["e12m3/d"] = "Tcuft/d", ["e3cuft/a"] = "v * 2.8316846592 < 100 ! ! e3 ! m3/a", ["e3cuft/d"] = "v * 2.8316846592 < 100 ! ! e3 ! m3/d", ["e3cuft/s"] = "v * 2.8316846592 < 100 ! ! e3 ! m3/s", ["e3m3/a"] = "v < 28.316846592 ! k ! M ! cuft/a", ["e3m3/d"] = "v < 28.316846592 ! k ! M ! cuft/d", ["e3m3/s"] = "v < 28.316846592 ! k ! M ! cuft/s", ["e3USgal/a"] = "v * 3.785411784 < 1000 ! ! e3 ! m3/a", ["e6cuft/a"] = "v * 2.8316846592 < 100 ! e3 ! e6 ! m3/a", ["e6cuft/d"] = "v * 2.8316846592 < 100 ! e3 ! e6 ! m3/d", ["e6cuft/s"] = "v * 2.8316846592 < 100 ! e3 ! e6 ! m3/s", ["e6m3/a"] = "v < 28.316846592 ! M ! G ! cuft/a", ["e6m3/d"] = "v < 28.316846592 ! M ! G ! cuft/d", ["e6m3/s"] = "v < 28.316846592 ! e6 ! e9 ! cuft/s", ["e6USgal/a"] = "v * 3.785411784 < 1000 ! e3 ! e6 ! m3/a", ["e9cuft/a"] = "m3/a", ["e9cuft/d"] = "v * 2.8316846592 < 100 ! e6 ! e9 ! m3/d", ["e9m3/a"] = "v < 28.316846592 ! G ! T ! cuft/a", ["e9m3/d"] = "v < 28.316846592 ! G ! T ! cuft/d", ["e9m3/s"] = "v < 28.316846592 ! e9 ! e12 ! cuft/s", ["e9USgal/a"] = "v * 3.785411784 < 1000 ! e6 ! e9 ! m3/a", ["e9USgal/s"] = "v * 3.785411784 < 1000 ! e6 ! e9 ! m3/s", ["nN"] = "gr-f", ["μN"] = "gr-f", ["mN"] = "oz-f", ["am"] = "in", ["cm"] = "in", ["dam"] = "ft", ["dm"] = "in", ["e12km"] = "e12mi", ["e12mi"] = "e12km", ["e3AU"] = "ly", ["e3km"] = "e3mi", ["e3mi"] = "e3km", ["e6km"] = "e6mi", ["e6mi"] = "e6km", ["e9km"] = "AU", ["e9mi"] = "e9km", ["Em"] = "mi", ["fm"] = "in", ["Gm"] = "mi", ["hm"] = "ft", ["km"] = "mi", ["mm"] = "in", ["Mm"] = "mi", ["nm"] = "in", ["Pm"] = "mi", ["pm"] = "in", ["Tm"] = "mi", ["Ym"] = "mi", ["ym"] = "in", ["Zm"] = "mi", ["zm"] = "in", ["μm"] = "in", ["e12lb"] = "v * 4.5359237 < 10 ! Mt ! Gt", ["e3lb"] = "v * 4.5359237 < 10 ! kg ! t", ["e3ozt"] = "v * 0.311034768 < 10 ! kg ! t", ["e3t"] = "LT ST", ["e6carat"] = "t", ["e6lb"] = "v * 4.5359237 < 10 ! t ! kilotonne", ["e6ozt"] = "lb kg", ["e6ST"] = "Mt", ["e6t"] = "LT ST", ["e9lb"] = "v * 4.5359237 < 10 ! kilotonne ! Mt", ["e9t"] = "LT ST", ["Gg"] = "lb", ["kg"] = "lb", ["mg"] = "gr", ["Mg"] = "LT ST", ["ng"] = "gr", ["μg"] = "gr", ["mBq"] = "fCi", ["kBq"] = "nCi", ["MBq"] = "μCi", ["GBq"] = "mCi", ["TBq"] = "Ci", ["PBq"] = "kCi", ["EBq"] = "kCi", ["fCi"] = "mBq", ["pCi"] = "Bq", ["nCi"] = "Bq", ["μCi"] = "kBq", ["mCi"] = "MBq", ["kCi"] = "TBq", ["MCi"] = "PBq", ["ns"] = "μs", ["μs"] = "ms", ["ms"] = "s", ["ks"] = "h", ["Ms"] = "week", ["Gs"] = "decade", ["Ts"] = "millennium", ["Ps"] = "million year", ["Es"] = "thousand million year", ["MK"] = "keVT", ["cL"] = "impoz usoz", ["cl"] = "impoz usoz", ["cm<sup>3</sup>"] = "cuin", ["dL"] = "impoz usoz", ["dl"] = "impoz usoz", ["mm<sup>3</sup>"] = "cuin", ["dm<sup>3</sup>"] = "cuin", ["e12cuft"] = "v * 2.8316846592 < 100 ! e9 ! e12 ! m3", ["e12impgal"] = "v * 4.54609 < 1000 ! T ! P ! l", ["e12m3"] = "v < 28.316846592 ! T ! P ! cuft", ["e12U.S.gal"] = "v * 3.785411784 < 1000 ! T ! P ! l", ["e12USgal"] = "v * 3.785411784 < 1000 ! T ! P ! l", ["e15cuft"] = "v * 2.8316846592 < 100 ! e12 ! e15 ! m3", ["e15m3"] = "Pcuft", ["e3bdft"] = "v * 0.23597372167 < 100 ! e3 ! e6 ! m3", ["e3cuft"] = "v * 2.8316846592 < 100 ! ! e3 ! m3", ["e3impgal"] = "v * 4.54609 < 1000 ! k ! M ! l", ["e3m3"] = "v < 28.316846592 ! k ! M ! cuft", ["e3U.S.gal"] = "v * 3.785411784 < 1000 ! k ! M ! l", ["e3USgal"] = "v * 3.785411784 < 1000 ! k ! M ! l", ["e6bdft"] = "v * 0.23597372167 < 100 ! e3 ! e6 ! m3", ["e6cuft"] = "v * 2.8316846592 < 100 ! e3 ! e6 ! m3", ["e6cuyd"] = "v * 7.64554857984 < 10 ! e3 ! e6 ! m3", ["e6impgal"] = "v * 4.54609 < 1000 ! M ! G ! l", ["e6L"] = "USgal", ["e6m3"] = "v < 28.316846592 ! M ! G ! cuft", ["e6U.S.gal"] = "v * 3.785411784 < 1000 ! M ! G ! l", ["e6USgal"] = "v * 3.785411784 < 1000 ! M ! G ! l", ["e9bdft"] = "v * 0.23597372167 < 100 ! e6 ! e9 ! m3", ["e9cuft"] = "v * 2.8316846592 < 100 ! e6 ! e9 ! m3", ["e9impgal"] = "v * 4.54609 < 1000 ! G ! T ! l", ["e9m3"] = "v < 28.316846592 ! G ! T ! cuft", ["e9U.S.gal"] = "v * 3.785411784 < 1000 ! G ! T ! l", ["e9USgal"] = "v * 3.785411784 < 1000 ! G ! T ! l", ["GL"] = "cuft", ["Gl"] = "cuft", ["kL"] = "cuft", ["kl"] = "cuft", ["km<sup>3</sup>"] = "cumi", ["mL"] = "impoz usoz", ["ml"] = "impoz usoz", ["Ml"] = "v < 28.316846592 ! e3 ! e6 ! cuft", ["ML"] = "v < 28.316846592 ! e3 ! e6 ! cuft", ["TL"] = "cumi", ["Tl"] = "cumi", ["μL"] = "cuin", ["μl"] = "cuin", } --------------------------------------------------------------------------- -- Do not change the data in this table because it is created by running -- -- a script that reads the wikitext from a wiki page (see note above). -- --------------------------------------------------------------------------- local link_exceptions = { -- Prefixed units with a linked article different from that of the base unit. -- Each key item is a prefixed symbol (not unitcode). ["mm<sup>2</sup>"] = "Square millimetre", ["cm<sup>2</sup>"] = "Square centimetre", ["dm<sup>2</sup>"] = "Square decimetre", ["km<sup>2</sup>"] = "Square kilometre", ["kJ"] = "Kilojoule", ["MJ"] = "Megajoule", ["GJ"] = "Gigajoule", ["TJ"] = "Terajoule", ["fm"] = "Femtometre", ["pm"] = "Picometre", ["nm"] = "Nanometre", ["μm"] = "Micrometre", ["mm"] = "Millimetre", ["cm"] = "Centimetre", ["dm"] = "Decimetre", ["dam"] = "Decametre", ["hm"] = "Hectometre", ["km"] = "Kilometre", ["Mm"] = "Megametre", ["Gm"] = "Gigametre", ["Tm"] = "Terametre", ["Pm"] = "Petametre", ["Em"] = "Exametre", ["Zm"] = "Zettametre", ["Ym"] = "Yottametre", ["μg"] = "Microgram", ["mg"] = "Milligram", ["kg"] = "Kilogram", ["Mg"] = "Tonne", ["yW"] = "Yoctowatt", ["zW"] = "Zeptowatt", ["aW"] = "Attowatt", ["fW"] = "Femtowatt", ["pW"] = "Picowatt", ["nW"] = "Nanowatt", ["μW"] = "Microwatt", ["mW"] = "Milliwatt", ["kW"] = "Kilowatt", ["MW"] = "Megawatt", ["GW"] = "Gigawatt", ["TW"] = "Terawatt", ["PW"] = "Petawatt", ["EW"] = "Exawatt", ["ZW"] = "Zettawatt", ["YW"] = "Yottawatt", ["as"] = "Attosecond", ["fs"] = "Femtosecond", ["ps"] = "Picosecond", ["ns"] = "Nanosecond", ["μs"] = "Microsecond", ["ms"] = "Millisecond", ["ks"] = "Kilosecond", ["Ms"] = "Megasecond", ["Gs"] = "Gigasecond", ["Ts"] = "Terasecond", ["Ps"] = "Petasecond", ["Es"] = "Exasecond", ["Zs"] = "Zettasecond", ["Ys"] = "Yottasecond", ["mm<sup>3</sup>"] = "Cubic millimetre", ["cm<sup>3</sup>"] = "Cubic centimetre", ["dm<sup>3</sup>"] = "Cubic decimetre", ["dam<sup>3</sup>"] = "Cubic decametre", ["km<sup>3</sup>"] = "Cubic kilometre", ["μL"] = "Microlitre", ["μl"] = "Microlitre", ["mL"] = "Millilitre", ["ml"] = "Millilitre", ["cL"] = "Centilitre", ["cl"] = "Centilitre", ["dL"] = "Decilitre", ["dl"] = "Decilitre", ["daL"] = "Decalitre", ["dal"] = "Decalitre", ["hL"] = "Hectolitre", ["hl"] = "Hectolitre", ["kL"] = "Kilolitre", ["kl"] = "Kilolitre", ["ML"] = "Megalitre", ["Ml"] = "Megalitre", ["GL"] = "Gigalitre", ["Gl"] = "Gigalitre", ["TL"] = "Teralitre", ["Tl"] = "Teralitre", ["PL"] = "Petalitre", ["Pl"] = "Petalitre", } --------------------------------------------------------------------------- -- Do not change the data in this table because it is created by running -- -- a script that reads the wikitext from a wiki page (see note above). -- --------------------------------------------------------------------------- local per_unit_fixups = { -- Automatically created per units of form "x/y" may have their unit type -- changed, for example, "length/time" is changed to "speed". -- Other adjustments can also be specified. ["/area"] = "per unit area", ["/volume"] = "per unit volume", ["area/area"] = "area per unit area", ["energy/length"] = "energy per unit length", ["energy/mass"] = "energy per unit mass", ["energy/time"] = { utype = "power", link = "Power (physics)" }, ["energy/volume"] = "energy per unit volume", ["force/area"] = { utype = "pressure", link = "Pressure" }, ["length/length"] = { utype = "gradient", link = "Grade (slope)" }, ["length/time"] = { utype = "speed", link = "Speed" }, ["length/time/time"] = { utype = "acceleration", link = "Acceleration" }, ["mass/area"] = { utype = "pressure", multiplier = 9.80665 }, ["mass/length"] = "linear density", ["mass/mass"] = "concentration", ["mass/power"] = "mass per unit power", ["mass/time"] = "mass per unit time", ["mass/volume"] = { utype = "density", link = "Density" }, ["power/mass"] = "power per unit mass", ["power/volume"] = { link = "Power density" }, ["pressure/length"] = "fracture gradient", ["speed/time"] = { utype = "acceleration", link = "Acceleration" }, ["volume/area"] = "volume per unit area", ["volume/length"] = "volume per unit length", ["volume/time"] = "flow", } return { all_units = all_units, default_exceptions = default_exceptions, link_exceptions = link_exceptions, per_unit_fixups = per_unit_fixups, } df9e48c56b5ed9957eaef10e36df353b161075f5 Module:Convert/text 828 48 112 111 2022-09-04T15:24:32Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- Text used by Module:Convert for enwiki. -- This is a separate module to simplify translation for use on another wiki. -- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki. -- Some units accept an SI prefix before the unit code, such as "kg" for kilogram. local SIprefixes = { -- The prefix field is what the prefix should be, if different from the prefix used. ['Y'] = { exponent = 24, name = 'yotta', }, ['Z'] = { exponent = 21, name = 'zetta', }, ['E'] = { exponent = 18, name = 'exa' , }, ['P'] = { exponent = 15, name = 'peta' , }, ['T'] = { exponent = 12, name = 'tera' , }, ['G'] = { exponent = 9, name = 'giga' , }, ['M'] = { exponent = 6, name = 'mega' , }, ['k'] = { exponent = 3, name = 'kilo' , }, ['h'] = { exponent = 2, name = 'hecto', }, ['da']= { exponent = 1, name = 'deca' , name_us = 'deka' }, ['d'] = { exponent = -1, name = 'deci' , }, ['c'] = { exponent = -2, name = 'centi', }, ['m'] = { exponent = -3, name = 'milli', }, ['μ'] = { exponent = -6, name = 'micro', }, -- key = 'GREEK SMALL LETTER MU' (U+03BC) utf-8 CE BC ['µ'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- key = 'MICRO SIGN' (U+00B5) utf-8 C2 B5 ['u'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- not an SI prefix, but allow for people typing this ['n'] = { exponent = -9, name = 'nano' , }, ['p'] = { exponent =-12, name = 'pico' , }, ['f'] = { exponent =-15, name = 'femto', }, ['a'] = { exponent =-18, name = 'atto' , }, ['z'] = { exponent =-21, name = 'zepto', }, ['y'] = { exponent =-24, name = 'yocto', }, } -- Some units can be qualified with one of the following prefixes, when linked. local customary_units = { { "US", link = "United States customary units" }, { "U.S.", link = "United States customary units" }, { "imperial", link = "Imperial units" }, { "imp", link = "Imperial units" }, } -- Names when using engineering notation (a prefix of "eN" where N is a number; example "e6km"). -- key = { "name", link = "article title", exponent = numeric_key_value } -- If lk=on and link is defined, the name of the number will appear as a link. local eng_scales = { ["3"] = { "thousand", exponent = 3 }, ["6"] = { "million", exponent = 6 }, ["9"] = { "billion", link = "1000000000 (number)", exponent = 9 }, ["12"] = { "trillion", link = "1000000000000 (number)", exponent = 12 }, ["15"] = { "quadrillion", link = "1000000000000000 (number)", exponent = 15 }, } local all_categories = { unit = "[[Category:Convert errors]]", option = "[[Category:Convert errors]]", warning = '[[Category:Convert invalid options]]', tracking = '[[Category:Convert tracking]]', } -- For some error messages, the following puts the wanted style around -- each unit code marked like '...%{ft%}...'. local unitcode_regex = '%%([{}])' local unitcode_replace = { ['{'] = '"', ['}'] = '"' } -- no longer need the more elaborate substitute used before 2013-09-28 -- All messages that may be displayed if a problem occurs. local all_messages = { -- Message format string: $1=title, $2=text, $3=category, $4=anchor. -- Each displayed message starts with "Convert:" so can easily locate by searching article. cvt_format = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[<i>[[Help:Convert messages#$4|<span title="Convert: $1">convert: $2</span>]]</i>]</sup>$3<span class="error"></span>', cvt_format2 = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[[Help:Convert messages#$4|<span title="Convert: $1">$2</span>]]</sup>$3<span class="error"></span>', cvt_format_preview = '<strong class="error">Error in convert: $1 [[Help:Convert messages#$4|(help)]]</strong>$3', -- Each of following messages is a table: -- { [1] = 'title', -- mouseover title text -- [2] = 'text', -- link text displayed in article -- [3] = 'category key', -- key to lookup category in all_categories -- [4] = 'anchor', -- anchor for link to relevant section on help page -- regex = gsub_regex, -- replace = gsub_table, -- } Mouseover title text Link text CatKey Anchor cvt_bad_input = { 'input "$1" must be a number and unit' , 'invalid input' , 'option', 'invalid_input' }, cvt_bad_num = { 'Value "$1" must be a number' , 'invalid number' , 'option', 'invalid_number' }, cvt_big_prec = { 'Precision "$1" is too large' , 'precision too large' , 'option', 'precision_too_large' }, cvt_invalid_num = { 'Number has overflowed' , 'number overflow' , 'option', 'number_overflow' }, cvt_no_num = { 'Needs the number to be converted' , 'needs a number' , 'option', 'needs_number' }, cvt_no_num2 = { 'Needs another number for a range' , 'needs another number', 'option', 'needs_another_number' }, cvt_bad_altitude = { '"$1" needs an integer' , 'invalid altitude' , 'option', 'invalid_altitude' }, cvt_bad_frac = { '"$1" needs an integer above 1' , 'invalid fraction' , 'option', 'invalid_fraction' }, cvt_bad_prec = { 'Precision "$1" must be an integer' , 'invalid precision' , 'option', 'invalid_precision' }, cvt_bad_sigfig = { '"$1" needs a positive integer' , 'invalid sigfig' , 'option', 'invalid_sigfig' }, cvt_empty_option = { 'Ignored empty option "$1"' , 'empty option' , 'option', 'empty_option' }, cvt_deprecated = { 'Option "$1" is deprecated' , '*' , 'option', 'deprecated_option', format = 'cvt_format2', nowarn = true }, cvt_no_spell = { 'Spelling is not available' , 'bug, ask for help' , 'option', 'ask_for_help' }, cvt_unknown_option = { 'Ignored invalid option "$1"' , 'invalid option' , 'option', 'invalid_option' }, cvt_wd_fail = { 'Unable to access Wikidata' , 'wikidata problem' , 'option', 'wikidata_problem' }, cvt_bad_default = { 'Unit "$1" has an invalid default' , 'bug, ask for help' , 'unit' , 'ask_for_help' }, cvt_bad_unit = { 'Unit "$1" is invalid here' , 'unit invalid here' , 'unit' , 'unit_invalid_here' }, cvt_no_default = { 'Unit "$1" has no default output unit' , 'bug, ask for help' , 'unit' , 'ask_for_help' }, cvt_no_unit = { 'Needs name of unit' , 'needs unit name' , 'unit' , 'needs_unit_name' }, cvt_unknown = { 'Unit name "$1" is not known' , 'unknown unit' , 'unit' , 'unknown_unit' }, cvt_should_be = { '$1' , 'ambiguous unit' , 'unit' , 'ambiguous_unit', regex = unitcode_regex, replace = unitcode_replace }, cvt_mismatch = { 'Cannot convert "$1" to "$2"' , 'unit mismatch' , 'unit' , 'unit_mismatch' }, cvt_bug_convert = { 'Bug: Cannot convert between specified units', 'bug, ask for help' , 'unit' , 'ask_for_help' }, cvt_lookup = { 'Unit "$1" is incorrectly defined' , 'bug, ask for help' , 'unit' , 'ask_for_help' }, } -- Text to join input value/unit with output value/unit. local disp_joins = { -- [1]=before output, [2]=after output, [3]=between outputs in a combination; default "; " -- [wantname] gives default abbr=off ["or"] = { " or " , "" , " or ", wantname = true }, ["sqbr-sp"] = { " [" , "]" }, ["sqbr-nbsp"] = { "&nbsp;[" , "]" }, ["comma"] = { ", " , "" , ", " }, ["slash-sp"] = { " / " , "" , wantname = true }, ["slash-nbsp"] = { "&nbsp;/ ", "" , wantname = true }, ["slash-nosp"] = { "/" , "" , wantname = true }, ["b"] = { " (" , ")" }, ["(or)"] = { " (" , ")", " or " }, ["br"] = { "<br />" , "" , wantname = true }, ["br()"] = { "<br />(" , ")", wantname = true }, } -- Text to separate values in a range. local range_types = { -- Specifying a table requires either: -- * "off" and "on" values (for "abbr=off" and "abbr=on"), or -- * "input" and "output" values (for LHS and RHS); -- other fields are optional. -- When "adj=on|abbr=off" applies, spaces in range text are replaced with hyphens. -- With "exception = true", that also occurs with "adj=on|abbr=on". -- If "adj" is defined here, that text (unchanged) is used with "adj=on". ["+"] = " + ", [","] = ",&nbsp;", [", and"] = ", and ", [", or"] = ", or ", ["by"] = " by ", ["-"] = "–", ["to about"] = " to about ", ["and"] = { off = " and ", on = " and ", exception = true }, ["and(-)"] = { input = " and ", output = "–" }, ["or"] = { off = " or " , on = " or " , exception = true }, ["to"] = { off = " to " , on = " to " , exception = true }, ["to(-)"] = { input = "&nbsp;to ", output = "–" }, ["+/-"] = { off = "&nbsp;±&nbsp;", on = "&nbsp;±&nbsp;", adj = "&nbsp;±&nbsp;", is_range_change = true }, ["by(x)"] = { input = " by ", output = " ×&nbsp;", out_range_x = true }, ["x"] = { off = " by ", on = " ×&nbsp;", abbr_range_x = true }, ["xx"] = "&nbsp;×&nbsp;", ["*"] = "×", ["/"] = "&thinsp;/&thinsp;", -- for a table of high/low temperatures with {{convert|83|/|63|F|disp=br()|abbr=values}} } local range_aliases = { -- ["alternative name for a range"] = "standard range name" ["–"] = "-", ["&ndash;"] = "-", ["×"] = "x", ["&times;"] = "x", ["±"] = "+/-", ["&plusmn;"] = "+/-", } -- Convert accepts range text delimited with whitespace, for example, {{convert|1 to 2|ft}}. -- In addition, the following "words" are accepted without spaces, for example, {{convert|1-2|ft}}. -- Words must be in correct order for searching, for example, 'x' after 'xx'. local range_words = { '-', '–', 'xx', 'x', '*' } local ranges = { types = range_types, aliases = range_aliases, words = range_words, } -- Valid option names. local en_option_name = { -- ["local text for option name"] = "en name used in this module" ["$"] = "$", ["abbr"] = "abbr", ["adj"] = "adj", ["altitude_ft"] = "altitude_ft", ["altitude_m"] = "altitude_m", ["comma"] = "comma", ["debug"] = "debug", ["disp"] = "disp", ["frac"] = "frac", ["input"] = "input", ["lang"] = "lang", ["lk"] = "lk", ["order"] = "order", ["qid"] = "qid", ["qual"] = "qual", ["qualifier"] = "qual", ["round"] = "round", ["sigfig"] = "sigfig", ["sing"] = "adj", -- "sing" is an old alias for "adj" ["sortable"] = "sortable", ["sp"] = "sp", ["spell"] = "spell", ["stylein"] = "stylein", ["styleout"] = "styleout", ["tracking"] = "tracking", } -- Valid option values. -- Convention: parms.opt_xxx refers to an option that is set here -- (not intended to be set by the template which invokes this module). -- Example: At enwiki, "abbr" includes: -- ["values"] = "opt_values" -- As a result, if the template uses abbr=values, Module:Convert sets: -- parms["opt_values"] = true -- parms["abbr"] = nil -- Therefore parms.abbr will be nil, or will have one of the listed values -- that do not start with "opt_". -- An option value of form "xxx?" is the same as "xxx" but shows the input as deprecated. local en_option_value = { ["$"] = 'TEXT', -- TEXT should be a currency symbol that will be used instead of "$" ["abbr"] = { -- ["local text for option value"] = "en value used in this module" ["def"] = "", -- ignored (some wrapper templates call convert with "abbr=def" to mean "default abbreviation") ["h"] = "on", -- abbr=on + use "h" for hand unit (default) ["hh"] = "opt_hand_hh", -- abbr=on + use "hh" for hand unit ["in"] = "in", -- use symbol for LHS unit ["none"] = "off", -- old name for "off" ["off"] = "off", -- use name for all units ["on"] = "on", -- use symbol for all units ["out"] = "out", -- use symbol for RHS unit (default) ["unit"] = "unit", -- abbr=on but abbreviate units only: e6km → million km (not ×10⁶ km) ["values"] = "opt_values", -- show only input and output numbers, not units ["~"] = "opt_also_symbol", -- show input unit symbol as well as name }, ["adj"] = { ["mid"] = "opt_adjectival, opt_adj_mid", -- adj=on with user-specified text after input unit (between input and output) ["off"] = "", -- ignored (off is the default) ["on"] = "opt_adjectival", -- unit name is singular and hyphenated ["pre"] = "opt_one_preunit", -- user-specified text before input unit ["ri0"] = "opt_ri=0", -- round input with precision = 0 ["ri1"] = "opt_ri=1", -- round input with precision = 1 ["ri2"] = "opt_ri=2", -- round input with precision = 2 ["ri3"] = "opt_ri=3", -- round input with precision = 3 }, ["altitude_ft"] = 'INTEGER', ["altitude_m"] = 'INTEGER', ["comma"] = { ["5"] = "opt_comma5", -- only use numsep grouping if 5 or more digits ["gaps"] = "opt_gaps", -- use gaps, not numsep, to separate groups of digits ["gaps3"] = "opt_gaps, opt_gaps3", -- group only in threes rather than default of no gap before a single digit after decimal mark ["off"] = "opt_nocomma", -- no numsep in input or output numbers }, ["debug"] = { ["yes"] = "opt_sortable_debug", -- make the normally hidden sort key visible }, ["disp"] = { ["5"] = "opt_round=5?", -- round output value to nearest 5 ["b"] = "b", -- join: '(...)' ["(or)"] = "(or)", -- join: '(...)' with 'or' between outputs in a combination ["br"] = "br", -- join: '<br />' ["br()"] = "br()", -- join: '<br />(...)' ["comma"] = "comma", -- join: ',' ["flip"] = "opt_flip", -- reverse order of input/output ["number"] = "opt_output_number_only", -- display output value (not input, and not output symbol/name) ["or"] = "or", -- join: 'or' ["out"] = "opt_output_only", ["output number only"] = "opt_output_number_only", ["output only"] = "opt_output_only", ["preunit"] = "opt_two_preunits", -- user-specified text before input and output units ["sqbr"] = "sqbr", -- join: '[...]' ["table"] = "opt_table", -- output is suitable for a table cell with align="right" ["tablecen"] = "opt_tablecen", -- output is suitable for a table cell with align="center" ["unit"] = "opt_input_unit_only", -- display input symbol/name (not output, and not input value) ["unit or text"] = "opt_input_unit_only, opt_ignore_error", -- display input symbol/name, or given unit code if not known ["unit2"] = "opt_output_unit_only", ["x"] = "x", -- join: <first>...<second> (user-specified text) }, ["frac"] = 'INTEGER', ["input"] = 'TEXT', -- TEXT should be value><space><unitcode> or <wikidata-property-id> ["lang"] = { -- language for output digits (both en and local digits are always accepted for input) ["en"] = "opt_lang_en", -- use en digits for numbers, regardless of local language ["local"] = "opt_lang_local", -- use local digits for numbers (default, although config can change default to en) }, ["lk"] = { ["in"] = "in", -- link LHS unit name or symbol ["off"] = "off", -- do not link: same as default except for hand unit ["on"] = "on", -- link all unit names or symbols (but not twice for the same unit) ["out"] = "out", -- link RHS unit name or symbol }, ["order"] = { ["flip"] = "opt_flip", -- reverse order of input/output ["out"] = "opt_order_out", -- do not show input; instead, use order in output combination, with the first output shown as the input }, ["qid"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier ["qual"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier ["round"] = { ["0.5"] = "opt_round=0.5", -- round output value to nearest 0.5 ["5"] = "opt_round=5", -- round output value to nearest 5 ["10"] = "opt_round=10", -- round output value to nearest 10 (same as but clearer than "|-1") ["25"] = "opt_round=25", -- round output value to nearest 25 ["50"] = "opt_round=50", -- round output value to nearest 50 ["each"] = "opt_round_each", -- using default precision in a range, round each output separately (default uses highest precision of each item in range) }, ["sigfig"] = 'INTEGER', ["sortable"] = { ["off"] = "", -- ignored (off is the default) ["on"] = "opt_sortable_on", -- output sort key for use in a sortable table, based on value from converting to a standard base unit ["debug"] = "opt_sortable_on, opt_sortable_debug", -- |sortable=debug is the same as |sortable=on|debug=yes }, ["sp"] = { ["us"] = "opt_sp_us", -- use U.S. spelling (like "meter" instead of default "metre") }, ["spell"] = { -- only English spelling is supported; not scientific notation; only some fractions ["in"] = "opt_spell_in", -- spell input value in words ["In"] = "opt_spell_in, opt_spell_upper", -- spell input value in words with first letter uppercase ["on"] = "opt_spell_in, opt_spell_out", -- spell input and output values in words ["On"] = "opt_spell_in, opt_spell_out, opt_spell_upper", -- same, with first letter of first word in result uppercase }, ["stylein"] = 'TEXT', ["styleout"] = 'TEXT', ["tracking"] = 'TEXT', } local titles = { ["frac"] = "Fraction/styles.css", ["sfrac"] = "Sfrac/styles.css", } return { SIprefixes = SIprefixes, all_categories = all_categories, all_messages = all_messages, currency = { ['$'] = true, ['£'] = true, ['€'] = true, ['₱'] = true, ['₽'] = true, ['¥'] = true }, customary_units = customary_units, disp_joins = disp_joins, en_option_name = en_option_name, en_option_value = en_option_value, eng_scales = eng_scales, ranges = ranges, titles = titles, } 05665ce7dee224b4474fd898266e157aab84691f Template:Cite journal 10 49 114 113 2022-09-04T15:24:32Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:Citation/CS1|citation |CitationClass=journal }}</includeonly><noinclude> {{documentation}} </noinclude> 50b33a0bde8c0dc83f3753f7873bcb448b565944 Module:Citation/CS1 828 50 116 115 2022-09-04T15:24:33Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain require ('Module:No globals'); --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- each of these counts against the Lua upvalue limit ]] local validation; -- functions in Module:Citation/CS1/Date_validation local utilities; -- functions in Module:Citation/CS1/Utilities local z ={}; -- table of tables in Module:Citation/CS1/Utilities local identifiers; -- functions and tables in Module:Citation/CS1/Identifiers local metadata; -- functions in Module:Citation/CS1/COinS local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist --[[------------------< P A G E S C O P E V A R I A B L E S >--------------- declare variables here that have page-wide scope that are not brought in from other modules; that are created here and used here ]] local added_deprecated_cat; -- Boolean flag so that the category is added only once local added_vanc_errs; -- Boolean flag so we only emit one Vancouver error / category local added_generic_name_errs; -- Boolean flag so we only emit one generic name error / category and stop testing names once an error is encountered local Frame; -- holds the module's frame table local is_preview_mode; -- true when article is in preview mode; false when using 'Preview page with this template' (previewing the module) local is_sandbox; -- true when using sandbox modules to render citation --[[--------------------------< F I R S T _ S E T >------------------------------------------------------------ Locates and returns the first set value in a table of values where the order established in the table, left-to-right (or top-to-bottom), is the order in which the values are evaluated. Returns nil if none are set. This version replaces the original 'for _, val in pairs do' and a similar version that used ipairs. With the pairs version the order of evaluation could not be guaranteed. With the ipairs version, a nil value would terminate the for-loop before it reached the actual end of the list. ]] local function first_set (list, count) local i = 1; while i <= count do -- loop through all items in list if utilities.is_set( list[i] ) then return list[i]; -- return the first set list member end i = i + 1; -- point to next end end --[[--------------------------< A D D _ V A N C _ E R R O R >---------------------------------------------------- Adds a single Vancouver system error message to the template's output regardless of how many error actually exist. To prevent duplication, added_vanc_errs is nil until an error message is emitted. added_vanc_errs is a Boolean declared in page scope variables above ]] local function add_vanc_error (source, position) if added_vanc_errs then return end added_vanc_errs = true; -- note that we've added this category utilities.set_message ('err_vancouver', {source, position}); end --[[--------------------------< I S _ S C H E M E >------------------------------------------------------------ does this thing that purports to be a URI scheme seem to be a valid scheme? The scheme is checked to see if it is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says: Scheme names consist of a sequence of characters beginning with a letter and followed by any combination of letters, digits, plus ("+"), period ("."), or hyphen ("-"). returns true if it does, else false ]] local function is_scheme (scheme) return scheme and scheme:match ('^%a[%a%d%+%.%-]*:'); -- true if scheme is set and matches the pattern end --[=[-------------------------< I S _ D O M A I N _ N A M E >-------------------------------------------------- Does this thing that purports to be a domain name seem to be a valid domain name? Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5 BNF defined here: https://tools.ietf.org/html/rfc4234 Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15; see also [[Single-letter second-level domain]] list of TLDs: https://www.iana.org/domains/root/db RFC 952 (modified by RFC 1123) requires the first and last character of a hostname to be a letter or a digit. Between the first and last characters the name may use letters, digits, and the hyphen. Also allowed are IPv4 addresses. IPv6 not supported domain is expected to be stripped of any path so that the last character in the last character of the TLD. tld is two or more alpha characters. Any preceding '//' (from splitting a URL with a scheme) will be stripped here. Perhaps not necessary but retained in case it is necessary for IPv4 dot decimal. There are several tests: the first character of the whole domain name including subdomains must be a letter or a digit internationalized domain name (ASCII characters with .xn-- ASCII Compatible Encoding (ACE) prefix xn-- in the TLD) see https://tools.ietf.org/html/rfc3490 single-letter/digit second-level domains in the .org, .cash, and .today TLDs q, x, and z SL domains in the .com TLD i and q SL domains in the .net TLD single-letter SL domains in the ccTLDs (where the ccTLD is two letters) two-character SL domains in gTLDs (where the gTLD is two or more letters) three-plus-character SL domains in gTLDs (where the gTLD is two or more letters) IPv4 dot-decimal address format; TLD not allowed returns true if domain appears to be a proper name and TLD or IPv4 address, else false ]=] local function is_domain_name (domain) if not domain then return false; -- if not set, abandon end domain = domain:gsub ('^//', ''); -- strip '//' from domain name if present; done here so we only have to do it once if not domain:match ('^[%w]') then -- first character must be letter or digit return false; end if domain:match ('^%a+:') then -- hack to detect things that look like s:Page:Title where Page: is namespace at Wikisource return false; end local patterns = { -- patterns that look like URLs '%f[%w][%w][%w%-]+[%w]%.%a%a+$', -- three or more character hostname.hostname or hostname.tld '%f[%w][%w][%w%-]+[%w]%.xn%-%-[%w]+$', -- internationalized domain name with ACE prefix '%f[%a][qxz]%.com$', -- assigned one character .com hostname (x.com times out 2015-12-10) '%f[%a][iq]%.net$', -- assigned one character .net hostname (q.net registered but not active 2015-12-10) '%f[%w][%w]%.%a%a$', -- one character hostname and ccTLD (2 chars) '%f[%w][%w][%w]%.%a%a+$', -- two character hostname and TLD '^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?', -- IPv4 address } for _, pattern in ipairs (patterns) do -- loop through the patterns list if domain:match (pattern) then return true; -- if a match then we think that this thing that purports to be a URL is a URL end end for _, d in ipairs ({'cash', 'company', 'today', 'org'}) do -- look for single letter second level domain names for these top level domains if domain:match ('%f[%w][%w]%.' .. d) then return true end end return false; -- no matches, we don't know what this thing is end --[[--------------------------< I S _ U R L >------------------------------------------------------------------ returns true if the scheme and domain parts of a URL appear to be a valid URL; else false. This function is the last step in the validation process. This function is separate because there are cases that are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external wikilinks. ]] local function is_url (scheme, domain) if utilities.is_set (scheme) then -- if scheme is set check it and domain return is_scheme (scheme) and is_domain_name (domain); else return is_domain_name (domain); -- scheme not set when URL is protocol-relative end end --[[--------------------------< S P L I T _ U R L >------------------------------------------------------------ Split a URL into a scheme, authority indicator, and domain. First remove Fully Qualified Domain Name terminator (a dot following TLD) (if any) and any path(/), query(?) or fragment(#). If protocol-relative URL, return nil scheme and domain else return nil for both scheme and domain. When not protocol-relative, get scheme, authority indicator, and domain. If there is an authority indicator (one or more '/' characters immediately following the scheme's colon), make sure that there are only 2. Any URL that does not have news: scheme must have authority indicator (//). TODO: are there other common schemes like news: that don't use authority indicator? Strip off any port and path; ]] local function split_url (url_str) local scheme, authority, domain; url_str = url_str:gsub ('([%a%d])%.?[/%?#].*$', '%1'); -- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of '//') if url_str:match ('^//%S*') then -- if there is what appears to be a protocol-relative URL domain = url_str:match ('^//(%S*)') elseif url_str:match ('%S-:/*%S+') then -- if there is what appears to be a scheme, optional authority indicator, and domain name scheme, authority, domain = url_str:match ('(%S-:)(/*)(%S+)'); -- extract the scheme, authority indicator, and domain portions if utilities.is_set (authority) then authority = authority:gsub ('//', '', 1); -- replace place 1 pair of '/' with nothing; if utilities.is_set(authority) then -- if anything left (1 or 3+ '/' where authority should be) then return scheme; -- return scheme only making domain nil which will cause an error message end else if not scheme:match ('^news:') then -- except for news:..., MediaWiki won't link URLs that do not have authority indicator; TODO: a better way to do this test? return scheme; -- return scheme only making domain nil which will cause an error message end end domain = domain:gsub ('(%a):%d+', '%1'); -- strip port number if present end return scheme, domain; end --[[--------------------------< L I N K _ P A R A M _ O K >--------------------------------------------------- checks the content of |title-link=, |series-link=, |author-link=, etc. for properly formatted content: no wikilinks, no URLs Link parameters are to hold the title of a Wikipedia article, so none of the WP:TITLESPECIALCHARACTERS are allowed: # < > [ ] | { } _ except the underscore which is used as a space in wiki URLs and # which is used for section links returns false when the value contains any of these characters. When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid URL (the |<param>-link= parameter is ok); else false when value appears to be a valid URL (the |<param>-link= parameter is NOT ok). ]] local function link_param_ok (value) local scheme, domain; if value:find ('[<>%[%]|{}]') then -- if any prohibited characters return false; end scheme, domain = split_url (value); -- get scheme or nil and domain or nil from URL; return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid URL end --[[--------------------------< L I N K _ T I T L E _ O K >--------------------------------------------------- Use link_param_ok() to validate |<param>-link= value and its matching |<title>= value. |<title>= may be wiki-linked but not when |<param>-link= has a value. This function emits an error message when that condition exists check <link> for inter-language interwiki-link prefix. prefix must be a MediaWiki-recognized language code and must begin with a colon. ]] local function link_title_ok (link, lorig, title, torig) local orig; if utilities.is_set (link) then -- don't bother if <param>-link doesn't have a value if not link_param_ok (link) then -- check |<param>-link= markup orig = lorig; -- identify the failing link parameter elseif title:find ('%[%[') then -- check |title= for wikilink markup orig = torig; -- identify the failing |title= parameter elseif link:match ('^%a+:') then -- if the link is what looks like an interwiki local prefix = link:match ('^(%a+):'):lower(); -- get the interwiki prefix if cfg.inter_wiki_map[prefix] then -- if prefix is in the map, must have preceding colon orig = lorig; -- flag as error end end end if utilities.is_set (orig) then link = ''; -- unset utilities.set_message ('err_bad_paramlink', orig); -- URL or wikilink in |title= with |title-link=; end return link; -- link if ok, empty string else end --[[--------------------------< C H E C K _ U R L >------------------------------------------------------------ Determines whether a URL string appears to be valid. First we test for space characters. If any are found, return false. Then split the URL into scheme and domain portions, or for protocol-relative (//example.com) URLs, just the domain. Use is_url() to validate the two portions of the URL. If both are valid, or for protocol-relative if domain is valid, return true, else false. Because it is different from a standard URL, and because this module used external_link() to make external links that work for standard and news: links, we validate newsgroup names here. The specification for a newsgroup name is at https://tools.ietf.org/html/rfc5536#section-3.1.4 ]] local function check_url( url_str ) if nil == url_str:match ("^%S+$") then -- if there are any spaces in |url=value it can't be a proper URL return false; end local scheme, domain; scheme, domain = split_url (url_str); -- get scheme or nil and domain or nil from URL; if 'news:' == scheme then -- special case for newsgroups return domain:match('^[%a%d%+%-_]+%.[%a%d%+%-_%.]*[%a%d%+%-_]$'); end return is_url (scheme, domain); -- return true if value appears to be a valid URL end --[=[-------------------------< I S _ P A R A M E T E R _ E X T _ W I K I L I N K >---------------------------- Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first non-space characters following the opening bracket appear to be a URL. The test will also find external wikilinks that use protocol-relative URLs. Also finds bare URLs. The frontier pattern prevents a match on interwiki-links which are similar to scheme:path URLs. The tests that find bracketed URLs are required because the parameters that call this test (currently |title=, |chapter=, |work=, and |publisher=) may have wikilinks and there are articles or redirects like '//Hus' so, while uncommon, |title=[[//Hus]] is possible as might be [[en://Hus]]. ]=] local function is_parameter_ext_wikilink (value) local scheme, domain; if value:match ('%f[%[]%[%a%S*:%S+.*%]') then -- if ext. wikilink with scheme and domain: [xxxx://yyyyy.zzz] scheme, domain = split_url (value:match ('%f[%[]%[(%a%S*:%S+).*%]')); elseif value:match ('%f[%[]%[//%S+.*%]') then -- if protocol-relative ext. wikilink: [//yyyyy.zzz] scheme, domain = split_url (value:match ('%f[%[]%[(//%S+).*%]')); elseif value:match ('%a%S*:%S+') then -- if bare URL with scheme; may have leading or trailing plain text scheme, domain = split_url (value:match ('(%a%S*:%S+)')); elseif value:match ('//%S+') then -- if protocol-relative bare URL: //yyyyy.zzz; may have leading or trailing plain text scheme, domain = split_url (value:match ('(//%S+)')); -- what is left should be the domain else return false; -- didn't find anything that is obviously a URL end return is_url (scheme, domain); -- return true if value appears to be a valid URL end --[[-------------------------< C H E C K _ F O R _ U R L >----------------------------------------------------- loop through a list of parameters and their values. Look at the value and if it has an external link, emit an error message. ]] local function check_for_url (parameter_list, error_list) for k, v in pairs (parameter_list) do -- for each parameter in the list if is_parameter_ext_wikilink (v) then -- look at the value; if there is a URL add an error message table.insert (error_list, utilities.wrap_style ('parameter', k)); end end end --[[--------------------------< S A F E _ F O R _ U R L >------------------------------------------------------ Escape sequences for content that will be used for URL descriptions ]] local function safe_for_url( str ) if str:match( "%[%[.-%]%]" ) ~= nil then utilities.set_message ('err_wikilink_in_url', {}); end return str:gsub( '[%[%]\n]', { ['['] = '&#91;', [']'] = '&#93;', ['\n'] = ' ' } ); end --[[--------------------------< E X T E R N A L _ L I N K >---------------------------------------------------- Format an external link with error checking ]] local function external_link (URL, label, source, access) local err_msg = ''; local domain; local path; local base_url; if not utilities.is_set (label) then label = URL; if utilities.is_set (source) then utilities.set_message ('err_bare_url_missing_title', {utilities.wrap_style ('parameter', source)}); else error (cfg.messages["bare_url_no_origin"]); end end if not check_url (URL) then utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}); end domain, path = URL:match ('^([/%.%-%+:%a%d]+)([/%?#].*)$'); -- split the URL into scheme plus domain and path if path then -- if there is a path portion path = path:gsub ('[%[%]]', {['['] = '%5b', [']'] = '%5d'}); -- replace '[' and ']' with their percent-encoded values URL = table.concat ({domain, path}); -- and reassemble end base_url = table.concat ({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wiki-markup URL if utilities.is_set (access) then -- access level (subscription, registration, limited) base_url = utilities.substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon end return base_url; end --[[--------------------------< D E P R E C A T E D _ P A R A M E T E R >-------------------------------------- Categorize and emit an error message when the citation contains one or more deprecated parameters. The function includes the offending parameter name to the error message. Only one error message is emitted regardless of the number of deprecated parameters in the citation. added_deprecated_cat is a Boolean declared in page scope variables above ]] local function deprecated_parameter(name) if not added_deprecated_cat then added_deprecated_cat = true; -- note that we've added this category utilities.set_message ('err_deprecated_params', {name}); -- add error message end end --[=[-------------------------< K E R N _ Q U O T E S >-------------------------------------------------------- Apply kerning to open the space between the quote mark provided by the module and a leading or trailing quote mark contained in a |title= or |chapter= parameter's value. This function will positive kern either single or double quotes: "'Unkerned title with leading and trailing single quote marks'" " 'Kerned title with leading and trailing single quote marks' " (in real life the kerning isn't as wide as this example) Double single quotes (italic or bold wiki-markup) are not kerned. Replaces Unicode quote marks in plain text or in the label portion of a [[L|D]] style wikilink with typewriter quote marks regardless of the need for kerning. Unicode quote marks are not replaced in simple [[D]] wikilinks. Call this function for chapter titles, for website titles, etc.; not for book titles. ]=] local function kern_quotes (str) local cap = ''; local wl_type, label, link; wl_type, label, link = utilities.is_wikilink (str); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]] if 1 == wl_type then -- [[D]] simple wikilink with or without quote marks if mw.ustring.match (str, '%[%[[\"“”\'‘’].+[\"“”\'‘’]%]%]') then -- leading and trailing quote marks str = utilities.substitute (cfg.presentation['kern-left'], str); str = utilities.substitute (cfg.presentation['kern-right'], str); elseif mw.ustring.match (str, '%[%[[\"“”\'‘’].+%]%]') then -- leading quote marks str = utilities.substitute (cfg.presentation['kern-left'], str); elseif mw.ustring.match (str, '%[%[.+[\"“”\'‘’]%]%]') then -- trailing quote marks str = utilities.substitute (cfg.presentation['kern-right'], str); end else -- plain text or [[L|D]]; text in label variable label = mw.ustring.gsub (label, '[“”]', '\"'); -- replace “” (U+201C & U+201D) with " (typewriter double quote mark) label = mw.ustring.gsub (label, '[‘’]', '\''); -- replace ‘’ (U+2018 & U+2019) with ' (typewriter single quote mark) cap = mw.ustring.match (label, "^([\"\'][^\'].+)"); -- match leading double or single quote but not doubled single quotes (italic markup) if utilities.is_set (cap) then label = utilities.substitute (cfg.presentation['kern-left'], cap); end cap = mw.ustring.match (label, "^(.+[^\'][\"\'])$") -- match trailing double or single quote but not doubled single quotes (italic markup) if utilities.is_set (cap) then label = utilities.substitute (cfg.presentation['kern-right'], cap); end if 2 == wl_type then str = utilities.make_wikilink (link, label); -- reassemble the wikilink else str = label; end end return str; end --[[--------------------------< F O R M A T _ S C R I P T _ V A L U E >---------------------------------------- |script-title= holds title parameters that are not written in Latin-based scripts: Chinese, Japanese, Arabic, Hebrew, etc. These scripts should not be italicized and may be written right-to-left. The value supplied by |script-title= is concatenated onto Title after Title has been wrapped in italic markup. Regardless of language, all values provided by |script-title= are wrapped in <bdi>...</bdi> tags to isolate RTL languages from the English left to right. |script-title= provides a unique feature. The value in |script-title= may be prefixed with a two-character ISO 639-1 language code and a colon: |script-title=ja:*** *** (where * represents a Japanese character) Spaces between the two-character code and the colon and the colon and the first script character are allowed: |script-title=ja : *** *** |script-title=ja: *** *** |script-title=ja :*** *** Spaces preceding the prefix are allowed: |script-title = ja:*** *** The prefix is checked for validity. If it is a valid ISO 639-1 language code, the lang attribute (lang="ja") is added to the <bdi> tag so that browsers can know the language the tag contains. This may help the browser render the script more correctly. If the prefix is invalid, the lang attribute is not added. At this time there is no error message for this condition. Supports |script-title=, |script-chapter=, |script-<periodical>= ]] local function format_script_value (script_value, script_param) local lang=''; -- initialize to empty string local name; if script_value:match('^%l%l%l?%s*:') then -- if first 3 or 4 non-space characters are script language prefix lang = script_value:match('^(%l%l%l?)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script if not utilities.is_set (lang) then utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['missing title part']}); -- prefix without 'title'; add error message return ''; -- script_value was just the prefix so return empty string end -- if we get this far we have prefix and script name = cfg.lang_code_remap[lang] or mw.language.fetchLanguageName( lang, cfg.this_wiki_code ); -- get language name so that we can use it to categorize if utilities.is_set (name) then -- is prefix a proper ISO 639-1 language code? script_value = script_value:gsub ('^%l+%s*:%s*', ''); -- strip prefix from script -- is prefix one of these language codes? if utilities.in_array (lang, cfg.script_lang_codes) then utilities.add_prop_cat ('script', {name, lang}) else utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['unknown language code']}); -- unknown script-language; add error message end lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute else utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['invalid language code']}); -- invalid language code; add error message lang = ''; -- invalid so set lang to empty string end else utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['missing prefix']}); -- no language code prefix; add error message end script_value = utilities.substitute (cfg.presentation['bdi'], {lang, script_value}); -- isolate in case script is RTL return script_value; end --[[--------------------------< S C R I P T _ C O N C A T E N A T E >------------------------------------------ Initially for |title= and |script-title=, this function concatenates those two parameter values after the script value has been wrapped in <bdi> tags. ]] local function script_concatenate (title, script, script_param) if utilities.is_set (script) then script = format_script_value (script, script_param); -- <bdi> tags, lang attribute, categorization, etc.; returns empty string on error if utilities.is_set (script) then title = title .. ' ' .. script; -- concatenate title and script title end end return title; end --[[--------------------------< W R A P _ M S G >-------------------------------------------------------------- Applies additional message text to various parameter values. Supplied string is wrapped using a message_list configuration taking one argument. Supports lower case text for {{citation}} templates. Additional text taken from citation_config.messages - the reason this function is similar to but separate from wrap_style(). ]] local function wrap_msg (key, str, lower) if not utilities.is_set ( str ) then return ""; end if true == lower then local msg; msg = cfg.messages[key]:lower(); -- set the message to lower case before return utilities.substitute ( msg, str ); -- including template text else return utilities.substitute ( cfg.messages[key], str ); end end --[[----------------< W I K I S O U R C E _ U R L _ M A K E >------------------- Makes a Wikisource URL from Wikisource interwiki-link. Returns the URL and appropriate label; nil else. str is the value assigned to |chapter= (or aliases) or |title= or |title-link= ]] local function wikisource_url_make (str) local wl_type, D, L; local ws_url, ws_label; local wikisource_prefix = table.concat ({'https://', cfg.this_wiki_code, '.wikisource.org/wiki/'}); wl_type, D, L = utilities.is_wikilink (str); -- wl_type is 0 (not a wikilink), 1 (simple wikilink), 2 (complex wikilink) if 0 == wl_type then -- not a wikilink; might be from |title-link= str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace if utilities.is_set (str) then ws_url = table.concat ({ -- build a Wikisource URL wikisource_prefix, -- prefix str, -- article title }); ws_label = str; -- label for the URL end elseif 1 == wl_type then -- simple wikilink: [[Wikisource:ws article]] str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace if utilities.is_set (str) then ws_url = table.concat ({ -- build a Wikisource URL wikisource_prefix, -- prefix str, -- article title }); ws_label = str; -- label for the URL end elseif 2 == wl_type then -- non-so-simple wikilink: [[Wikisource:ws article|displayed text]] ([[L|D]]) str = L:match ('^[Ww]ikisource:(.+)') or L:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace if utilities.is_set (str) then ws_label = D; -- get ws article name from display portion of interwiki link ws_url = table.concat ({ -- build a Wikisource URL wikisource_prefix, -- prefix str, -- article title without namespace from link portion of wikilink }); end end if ws_url then ws_url = mw.uri.encode (ws_url, 'WIKI'); -- make a usable URL ws_url = ws_url:gsub ('%%23', '#'); -- undo percent-encoding of fragment marker end return ws_url, ws_label, L or D; -- return proper URL or nil and a label or nil end --[[----------------< F O R M A T _ P E R I O D I C A L >----------------------- Format the three periodical parameters: |script-<periodical>=, |<periodical>=, and |trans-<periodical>= into a single Periodical meta-parameter. ]] local function format_periodical (script_periodical, script_periodical_source, periodical, trans_periodical) if not utilities.is_set (periodical) then periodical = ''; -- to be safe for concatenation else periodical = utilities.wrap_style ('italic-title', periodical); -- style end periodical = script_concatenate (periodical, script_periodical, script_periodical_source); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped if utilities.is_set (trans_periodical) then trans_periodical = utilities.wrap_style ('trans-italic-title', trans_periodical); if utilities.is_set (periodical) then periodical = periodical .. ' ' .. trans_periodical; else -- here when trans-periodical without periodical or script-periodical periodical = trans_periodical; utilities.set_message ('err_trans_missing_title', {'periodical'}); end end return periodical; end --[[------------------< F O R M A T _ C H A P T E R _ T I T L E >--------------- Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=, and |chapter-url= into a single chapter meta- parameter (chapter_url_source used for error messages). ]] local function format_chapter_title (script_chapter, script_chapter_source, chapter, chapter_source, trans_chapter, trans_chapter_source, chapter_url, chapter_url_source, no_quotes, access) local ws_url, ws_label, L = wikisource_url_make (chapter); -- make a wikisource URL and label from a wikisource interwiki link if ws_url then ws_label = ws_label:gsub ('_', ' '); -- replace underscore separators with space characters chapter = ws_label; end if not utilities.is_set (chapter) then chapter = ''; -- to be safe for concatenation else if false == no_quotes then chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from module provided quote marks chapter = utilities.wrap_style ('quoted-title', chapter); end end chapter = script_concatenate (chapter, script_chapter, script_chapter_source); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped if utilities.is_set (chapter_url) then chapter = external_link (chapter_url, chapter, chapter_url_source, access); -- adds bare_url_missing_title error if appropriate elseif ws_url then chapter = external_link (ws_url, chapter .. '&nbsp;', 'ws link in chapter'); -- adds bare_url_missing_title error if appropriate; space char to move icon away from chap text; TODO: better way to do this? chapter = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, chapter}); end if utilities.is_set (trans_chapter) then trans_chapter = utilities.wrap_style ('trans-quoted-title', trans_chapter); if utilities.is_set (chapter) then chapter = chapter .. ' ' .. trans_chapter; else -- here when trans_chapter without chapter or script-chapter chapter = trans_chapter; chapter_source = trans_chapter_source:match ('trans%-?(.+)'); -- when no chapter, get matching name from trans-<param> utilities.set_message ('err_trans_missing_title', {chapter_source}); end end return chapter; end --[[----------------< H A S _ I N V I S I B L E _ C H A R S >------------------- This function searches a parameter's value for non-printable or invisible characters. The search stops at the first match. This function will detect the visible replacement character when it is part of the Wikisource. Detects but ignores nowiki and math stripmarkers. Also detects other named stripmarkers (gallery, math, pre, ref) and identifies them with a slightly different error message. See also coins_cleanup(). Output of this function is an error message that identifies the character or the Unicode group, or the stripmarker that was detected along with its position (or, for multi-byte characters, the position of its first byte) in the parameter value. ]] local function has_invisible_chars (param, v) local position = ''; -- position of invisible char or starting position of stripmarker local capture; -- used by stripmarker detection to hold name of the stripmarker local stripmarker; -- boolean set true when a stripmarker is found capture = string.match (v, '[%w%p ]*'); -- test for values that are simple ASCII text and bypass other tests if true if capture == v then -- if same there are no Unicode characters return; end for _, invisible_char in ipairs (cfg.invisible_chars) do local char_name = invisible_char[1]; -- the character or group name local pattern = invisible_char[2]; -- the pattern used to find it position, _, capture = mw.ustring.find (v, pattern); -- see if the parameter value contains characters that match the pattern if position and (cfg.invisible_defs.zwj == capture) then -- if we found a zero-width joiner character if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts position = nil; -- unset position elseif cfg.emoji[mw.ustring.codepoint (v, position+1)] then -- is zwj followed by a character listed in emoji{}? position = nil; -- unset position end end if position then if 'nowiki' == capture or 'math' == capture or -- nowiki and math stripmarkers (not an error condition) ('templatestyles' == capture and utilities.in_array (param, {'id', 'quote'})) then -- templatestyles stripmarker allowed in these parameters stripmarker = true; -- set a flag elseif true == stripmarker and cfg.invisible_defs.del == capture then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker position = nil; -- unset else local err_msg; if capture and not (cfg.invisible_defs.del == capture or cfg.invisible_defs.zwj == capture) then err_msg = capture .. ' ' .. char_name; else err_msg = char_name .. ' ' .. 'character'; end utilities.set_message ('err_invisible_char', {err_msg, utilities.wrap_style ('parameter', param), position}); -- add error message return; -- and done with this parameter end end end end --[[-------------------< A R G U M E N T _ W R A P P E R >---------------------- Argument wrapper. This function provides support for argument mapping defined in the configuration file so that multiple names can be transparently aliased to single internal variable. ]] local function argument_wrapper ( args ) local origin = {}; return setmetatable({ ORIGIN = function ( self, k ) local dummy = self[k]; -- force the variable to be loaded. return origin[k]; end }, { __index = function ( tbl, k ) if origin[k] ~= nil then return nil; end local args, list, v = args, cfg.aliases[k]; if type( list ) == 'table' then v, origin[k] = utilities.select_one ( args, list, 'err_redundant_parameters' ); if origin[k] == nil then origin[k] = ''; -- Empty string, not nil end elseif list ~= nil then v, origin[k] = args[list], list; else -- maybe let through instead of raising an error? -- v, origin[k] = args[k], k; error( cfg.messages['unknown_argument_map'] .. ': ' .. k); end -- Empty strings, not nil; if v == nil then v = ''; origin[k] = ''; end tbl = rawset( tbl, k, v ); return v; end, }); end --[[--------------------------< N O W R A P _ D A T E >------------------------- When date is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>. When date is DD MMMM YYYY or is MMMM DD, YYYY then wrap in nowrap span: <span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY DOES NOT yet support MMMM YYYY or any of the date ranges. ]] local function nowrap_date (date) local cap = ''; local cap2 = ''; if date:match("^%d%d%d%d%-%d%d%-%d%d$") then date = utilities.substitute (cfg.presentation['nowrap1'], date); elseif date:match("^%a+%s*%d%d?,%s+%d%d%d%d$") or date:match ("^%d%d?%s*%a+%s+%d%d%d%d$") then cap, cap2 = string.match (date, "^(.*)%s+(%d%d%d%d)$"); date = utilities.substitute (cfg.presentation['nowrap2'], {cap, cap2}); end return date; end --[[--------------------------< S E T _ T I T L E T Y P E >--------------------- This function sets default title types (equivalent to the citation including |type=<default value>) for those templates that have defaults. Also handles the special case where it is desirable to omit the title type from the rendered citation (|type=none). ]] local function set_titletype (cite_class, title_type) if utilities.is_set (title_type) then if 'none' == cfg.keywords_xlate[title_type] then title_type = ''; -- if |type=none then type parameter not displayed end return title_type; -- if |type= has been set to any other value use that value end return cfg.title_types [cite_class] or ''; -- set template's default title type; else empty string for concatenation end --[[--------------------------< S A F E _ J O I N >----------------------------- Joins a sequence of strings together while checking for duplicate separation characters. ]] local function safe_join( tbl, duplicate_char ) local f = {}; -- create a function table appropriate to type of 'duplicate character' if 1 == #duplicate_char then -- for single byte ASCII characters use the string library functions f.gsub = string.gsub f.match = string.match f.sub = string.sub else -- for multi-byte characters use the ustring library functions f.gsub = mw.ustring.gsub f.match = mw.ustring.match f.sub = mw.ustring.sub end local str = ''; -- the output string local comp = ''; -- what does 'comp' mean? local end_chr = ''; local trim; for _, value in ipairs( tbl ) do if value == nil then value = ''; end if str == '' then -- if output string is empty str = value; -- assign value to it (first time through the loop) elseif value ~= '' then if value:sub(1, 1) == '<' then -- special case of values enclosed in spans and other markup. comp = value:gsub( "%b<>", "" ); -- remove HTML markup (<span>string</span> -> string) else comp = value; end -- typically duplicate_char is sepc if f.sub(comp, 1, 1) == duplicate_char then -- is first character same as duplicate_char? why test first character? -- Because individual string segments often (always?) begin with terminal punct for the -- preceding segment: 'First element' .. 'sepc next element' .. etc.? trim = false; end_chr = f.sub(str, -1, -1); -- get the last character of the output string -- str = str .. "<HERE(enchr=" .. end_chr .. ")" -- debug stuff? if end_chr == duplicate_char then -- if same as separator str = f.sub(str, 1, -2); -- remove it elseif end_chr == "'" then -- if it might be wiki-markup if f.sub(str, -3, -1) == duplicate_char .. "''" then -- if last three chars of str are sepc'' str = f.sub(str, 1, -4) .. "''"; -- remove them and add back '' elseif f.sub(str, -5, -1) == duplicate_char .. "]]''" then -- if last five chars of str are sepc]]'' trim = true; -- why? why do this and next differently from previous? elseif f.sub(str, -4, -1) == duplicate_char .. "]''" then -- if last four chars of str are sepc]'' trim = true; -- same question end elseif end_chr == "]" then -- if it might be wiki-markup if f.sub(str, -3, -1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink trim = true; elseif f.sub(str, -3, -1) == duplicate_char .. '"]' then -- if last three chars of str are sepc"] quoted external link trim = true; elseif f.sub(str, -2, -1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link trim = true; elseif f.sub(str, -4, -1) == duplicate_char .. "'']" then -- normal case when |url=something & |title=Title. trim = true; end elseif end_chr == " " then -- if last char of output string is a space if f.sub(str, -2, -1) == duplicate_char .. " " then -- if last two chars of str are <sepc><space> str = f.sub(str, 1, -3); -- remove them both end end if trim then if value ~= comp then -- value does not equal comp when value contains HTML markup local dup2 = duplicate_char; if f.match(dup2, "%A" ) then dup2 = "%" .. dup2; end -- if duplicate_char not a letter then escape it value = f.gsub(value, "(%b<>)" .. dup2, "%1", 1 ) -- remove duplicate_char if it follows HTML markup else value = f.sub(value, 2, -1 ); -- remove duplicate_char when it is first character end end end str = str .. value; -- add it to the output string end end return str; end --[[--------------------------< I S _ S U F F I X >----------------------------- returns true if suffix is properly formed Jr, Sr, or ordinal in the range 1–9. Puncutation not allowed. ]] local function is_suffix (suffix) if utilities.in_array (suffix, {'Jr', 'Sr', 'Jnr', 'Snr', '1st', '2nd', '3rd'}) or suffix:match ('^%dth$') then return true; end return false; end --[[--------------------< I S _ G O O D _ V A N C _ N A M E >------------------- For Vancouver style, author/editor names are supposed to be rendered in Latin (read ASCII) characters. When a name uses characters that contain diacritical marks, those characters are to be converted to the corresponding Latin character. When a name is written using a non-Latin alphabet or logogram, that name is to be transliterated into Latin characters. The module doesn't do this so editors may/must. This test allows |first= and |last= names to contain any of the letters defined in the four Unicode Latin character sets [http://www.unicode.org/charts/PDF/U0000.pdf C0 Controls and Basic Latin] 0041–005A, 0061–007A [http://www.unicode.org/charts/PDF/U0080.pdf C1 Controls and Latin-1 Supplement] 00C0–00D6, 00D8–00F6, 00F8–00FF [http://www.unicode.org/charts/PDF/U0100.pdf Latin Extended-A] 0100–017F [http://www.unicode.org/charts/PDF/U0180.pdf Latin Extended-B] 0180–01BF, 01C4–024F |lastn= also allowed to contain hyphens, spaces, and apostrophes. (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/) |firstn= also allowed to contain hyphens, spaces, apostrophes, and periods This original test: if nil == mw.ustring.find (last, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%']*$") or nil == mw.ustring.find (first, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%'%.]+[2-6%a]*$") then was written outside of the code editor and pasted here because the code editor gets confused between character insertion point and cursor position. The test has been rewritten to use decimal character escape sequence for the individual bytes of the Unicode characters so that it is not necessary to use an external editor to maintain this code. \195\128-\195\150 – À-Ö (U+00C0–U+00D6 – C0 controls) \195\152-\195\182 – Ø-ö (U+00D8-U+00F6 – C0 controls) \195\184-\198\191 – ø-ƿ (U+00F8-U+01BF – C0 controls, Latin extended A & B) \199\132-\201\143 – DŽ-ɏ (U+01C4-U+024F – Latin extended B) ]] local function is_good_vanc_name (last, first, suffix, position) if not suffix then if first:find ('[,%s]') then -- when there is a space or comma, might be first name/initials + generational suffix first = first:match ('(.-)[,%s]+'); -- get name/initials suffix = first:match ('[,%s]+(.+)$'); -- get generational suffix end end if utilities.is_set (suffix) then if not is_suffix (suffix) then add_vanc_error (cfg.err_msg_supl.suffix, position); return false; -- not a name with an appropriate suffix end end if nil == mw.ustring.find (last, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%']*$") or nil == mw.ustring.find (first, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%'%.]*$") then add_vanc_error (cfg.err_msg_supl['non-Latin char'], position); return false; -- not a string of Latin characters; Vancouver requires Romanization end; return true; end --[[--------------------------< R E D U C E _ T O _ I N I T I A L S >------------------------------------------ Attempts to convert names to initials in support of |name-list-style=vanc. Names in |firstn= may be separated by spaces or hyphens, or for initials, a period. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35062/. Vancouver style requires family rank designations (Jr, II, III, etc.) to be rendered as Jr, 2nd, 3rd, etc. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35085/. This code only accepts and understands generational suffix in the Vancouver format because Roman numerals look like, and can be mistaken for, initials. This function uses ustring functions because firstname initials may be any of the Unicode Latin characters accepted by is_good_vanc_name (). ]] local function reduce_to_initials(first, position) local name, suffix = mw.ustring.match(first, "^(%u+) ([%dJS][%drndth]+)$"); if not name then -- if not initials and a suffix name = mw.ustring.match(first, "^(%u+)$"); -- is it just initials? end if name then -- if first is initials with or without suffix if 3 > mw.ustring.len (name) then -- if one or two initials if suffix then -- if there is a suffix if is_suffix (suffix) then -- is it legitimate? return first; -- one or two initials and a valid suffix so nothing to do else add_vanc_error (cfg.err_msg_supl.suffix, position); -- one or two initials with invalid suffix so error message return first; -- and return first unmolested end else return first; -- one or two initials without suffix; nothing to do end end end -- if here then name has 3 or more uppercase letters so treat them as a word local initials, names = {}, {}; -- tables to hold name parts and initials local i = 1; -- counter for number of initials names = mw.text.split (first, '[%s,]+'); -- split into a table of names and possible suffix while names[i] do -- loop through the table if 1 < i and names[i]:match ('[%dJS][%drndth]+%.?$') then -- if not the first name, and looks like a suffix (may have trailing dot) names[i] = names[i]:gsub ('%.', ''); -- remove terminal dot if present if is_suffix (names[i]) then -- if a legitimate suffix table.insert (initials, ' ' .. names[i]); -- add a separator space, insert at end of initials table break; -- and done because suffix must fall at the end of a name end -- no error message if not a suffix; possibly because of Romanization end if 3 > i then table.insert (initials, mw.ustring.sub(names[i], 1, 1)); -- insert the initial at end of initials table end i = i + 1; -- bump the counter end return table.concat(initials) -- Vancouver format does not include spaces. end --[[--------------------------< L I S T _ P E O P L E >-------------------------- Formats a list of people (authors, contributors, editors, interviewers, translators) names in the list will be linked when |<name>-link= has a value |<name>-mask- does NOT have a value; masked names are presumed to have been rendered previously so should have been linked there when |<name>-mask=0, the associated name is not rendered ]] local function list_people (control, people, etal) local sep; local namesep; local format = control.format; local maximum = control.maximum; local name_list = {}; if 'vanc' == format then -- Vancouver-like name styling? sep = cfg.presentation['sep_nl_vanc']; -- name-list separator between names is a comma namesep = cfg.presentation['sep_name_vanc']; -- last/first separator is a space else sep = cfg.presentation['sep_nl']; -- name-list separator between names is a semicolon namesep = cfg.presentation['sep_name']; -- last/first separator is <comma><space> end if sep:sub (-1, -1) ~= " " then sep = sep .. " " end if utilities.is_set (maximum) and maximum < 1 then return "", 0; end -- returned 0 is for EditorCount; not used for other names for i, person in ipairs (people) do if utilities.is_set (person.last) then local mask = person.mask; local one; local sep_one = sep; if utilities.is_set (maximum) and i > maximum then etal = true; break; end if mask then local n = tonumber (mask); -- convert to a number if it can be converted; nil else if n then one = 0 ~= n and string.rep("&mdash;", n) or nil; -- make a string of (n > 0) mdashes, nil else, to replace name person.link = nil; -- don't create link to name if name is replaces with mdash string or has been set nil else one = mask; -- replace name with mask text (must include name-list separator) sep_one = " "; -- modify name-list separator end else one = person.last; -- get surname local first = person.first -- get given name if utilities.is_set (first) then if ("vanc" == format) then -- if Vancouver format one = one:gsub ('%.', ''); -- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/) if not person.corporate and is_good_vanc_name (one, first, nil, i) then -- and name is all Latin characters; corporate authors not tested first = reduce_to_initials (first, i); -- attempt to convert first name(s) to initials end end one = one .. namesep .. first; end end if utilities.is_set (person.link) then one = utilities.make_wikilink (person.link, one); -- link author/editor end if one then -- if <one> has a value (name, mdash replacement, or mask text replacement) table.insert (name_list, one); -- add it to the list of names table.insert (name_list, sep_one); -- add the proper name-list separator end end end local count = #name_list / 2; -- (number of names + number of separators) divided by 2 if 0 < count then if 1 < count and not etal then if 'amp' == format then name_list[#name_list-2] = " & "; -- replace last separator with ampersand text elseif 'and' == format then if 2 == count then name_list[#name_list-2] = cfg.presentation.sep_nl_and; -- replace last separator with 'and' text else name_list[#name_list-2] = cfg.presentation.sep_nl_end; -- replace last separator with '(sep) and' text end end end name_list[#name_list] = nil; -- erase the last separator end local result = table.concat (name_list); -- construct list if etal and utilities.is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list result = result .. sep .. ' ' .. cfg.messages['et al']; -- we've got a last-first list and etal so add et al. end return result, count; -- return name-list string and count of number of names (count used for editor names only) end --[[--------------------< M A K E _ C I T E R E F _ I D >----------------------- Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise returns an empty string. namelist is one of the contributor-, author-, or editor-name lists chosen in that order. year is Year or anchor_year. ]] local function make_citeref_id (namelist, year) local names={}; -- a table for the one to four names and year for i,v in ipairs (namelist) do -- loop through the list and take up to the first four last names names[i] = v.last if i == 4 then break end -- if four then done end table.insert (names, year); -- add the year at the end local id = table.concat(names); -- concatenate names and year for CITEREF id if utilities.is_set (id) then -- if concatenation is not an empty string return "CITEREF" .. id; -- add the CITEREF portion else return ''; -- return an empty string; no reason to include CITEREF id in this citation end end --[[--------------------------< C I T E _ C L A S S _A T T R I B U T E _M A K E >------------------------------ construct <cite> tag class attribute for this citation. <cite_class> – config.CitationClass from calling template <mode> – value from |mode= parameter ]] local function cite_class_attribute_make (cite_class, mode) local class_t = {}; table.insert (class_t, 'citation'); -- required for blue highlight if 'citation' ~= cite_class then table.insert (class_t, cite_class); -- identify this template for user css table.insert (class_t, utilities.is_set (mode) and mode or 'cs1'); -- identify the citation style for user css or javascript else table.insert (class_t, utilities.is_set (mode) and mode or 'cs2'); -- identify the citation style for user css or javascript end for _, prop_key in ipairs (z.prop_keys_t) do table.insert (class_t, prop_key); -- identify various properties for user css or javascript end return table.concat (class_t, ' '); -- make a big string and done end --[[---------------------< N A M E _ H A S _ E T A L >-------------------------- Evaluates the content of name parameters (author, editor, etc.) for variations on the theme of et al. If found, the et al. is removed, a flag is set to true and the function returns the modified name and the flag. This function never sets the flag to false but returns its previous state because it may have been set by previous passes through this function or by the associated |display-<names>=etal parameter ]] local function name_has_etal (name, etal, nocat, param) if utilities.is_set (name) then -- name can be nil in which case just return local patterns = cfg.et_al_patterns; -- get patterns from configuration for _, pattern in ipairs (patterns) do -- loop through all of the patterns if name:match (pattern) then -- if this 'et al' pattern is found in name name = name:gsub (pattern, ''); -- remove the offending text etal = true; -- set flag (may have been set previously here or by |display-<names>=etal) if not nocat then -- no categorization for |vauthors= utilities.set_message ('err_etal', {param}); -- and set an error if not added end end end end return name, etal; end --[[---------------------< N A M E _ I S _ N U M E R I C >---------------------- Add maint cat when name parameter value does not contain letters. Does not catch mixed alphanumeric names so |last=A. Green (1922-1987) does not get caught in the current version of this test but |first=(1888) is caught. returns nothing ]] local function name_is_numeric (name, list_name) if utilities.is_set (name) then if mw.ustring.match (name, '^[%A]+$') then -- when name does not contain any letters utilities.set_message ('maint_numeric_names', cfg.special_case_translation [list_name]); -- add a maint cat for this template end end end --[[-----------------< N A M E _ H A S _ M U L T _ N A M E S >------------------ Evaluates the content of last/surname (authors etc.) parameters for multiple names. Multiple names are indicated if there is more than one comma or any "unescaped" semicolons. Escaped semicolons are ones used as part of selected HTML entities. If the condition is met, the function adds the multiple name maintenance category. returns nothing ]] local function name_has_mult_names (name, list_name) local _, commas, semicolons, nbsps; if utilities.is_set (name) then _, commas = name:gsub (',', ''); -- count the number of commas _, semicolons = name:gsub (';', ''); -- count the number of semicolons -- nbsps probably should be its own separate count rather than merged in -- some way with semicolons because Lua patterns do not support the -- grouping operator that regex does, which means there is no way to add -- more entities to escape except by adding more counts with the new -- entities _, nbsps = name:gsub ('&nbsp;',''); -- count nbsps -- There is exactly 1 semicolon per &nbsp; entity, so subtract nbsps -- from semicolons to 'escape' them. If additional entities are added, -- they also can be subtracted. if 1 < commas or 0 < (semicolons - nbsps) then utilities.set_message ('maint_mult_names', cfg.special_case_translation [list_name]); -- add a maint message end end end --[=[-------------------------< I S _ G E N E R I C >---------------------------------------------------------- Compares values assigned to various parameters according to the string provided as <item> in the function call. <item> can have on of two values: 'generic_names' – for name-holding parameters: |last=, |first=, |editor-last=, etc 'generic_titles' – for |title= There are two types of generic tests. The 'accept' tests look for a pattern that should not be rejected by the 'reject' test. For example, |author=[[John Smith (author)|Smith, John]] would be rejected by the 'author' reject test. But piped wikilinks with 'author' disambiguation should not be rejected so the 'accept' test prevents that from happening. Accept tests are always performed before reject tests. Each of the 'accept' and 'reject' sequence tables hold tables for en.wiki (['en']) and local.wiki (['local']) that each can hold a test sequence table The sequence table holds, at index [1], a test pattern, and, at index [2], a boolean control value. The control value tells string.find() or mw.ustring.find() to do plain-text search (true) or a pattern search (false). The intent of all this complexity is to make these searches as fast as possible so that we don't run out of processing time on very large articles. Returns true when a reject test finds the pattern or string false when an accept test finds the pattern or string nil else ]=] local function is_generic (item, value, wiki) local test_val; local str_lower = { -- use string.lower() for en.wiki (['en']) and use mw.ustring.lower() or local.wiki (['local']) ['en'] = string.lower, ['local'] = mw.ustring.lower, } local str_find = { -- use string.find() for en.wiki (['en']) and use mw.ustring.find() or local.wiki (['local']) ['en'] = string.find, ['local'] = mw.ustring.find, } local function test (val, test_t, wiki) -- local function to do the testing; <wiki> selects lower() and find() functions val = test_t[2] and str_lower[wiki](value) or val; -- when <test_t[2]> set to 'true', plaintext search using lowercase value return str_find[wiki] (val, test_t[1], 1, test_t[2]); -- return nil when not found or matched end local test_types_t = {'accept', 'reject'}; -- test accept patterns first, then reject patterns local wikis_t = {'en', 'local'}; -- do tests for each of these keys; en.wiki first, local.wiki second for _, test_type in ipairs (test_types_t) do -- for each test type for _, generic_value in pairs (cfg.special_case_translation[item][test_type]) do -- spin through the list of generic value fragments to accept or reject for _, wiki in ipairs (wikis_t) do if generic_value[wiki] then if test (value, generic_value[wiki], wiki) then -- go do the test return ('reject' == test_type); -- param value rejected, return true; false else end end end end end end --[[--------------------------< N A M E _ I S _ G E N E R I C >------------------------------------------------ calls is_generic() to determine if <name> is a 'generic name' listed in cfg.generic_names; <name_alias> is the parameter name used in error messaging ]] local function name_is_generic (name, name_alias) if not added_generic_name_errs and is_generic ('generic_names', name) then utilities.set_message ('err_generic_name', name_alias); -- set an error message added_generic_name_errs = true; end end --[[--------------------------< N A M E _ C H E C K S >-------------------------------------------------------- This function calls various name checking functions used to validate the content of the various name-holding parameters. ]] local function name_checks (last, first, list_name, last_alias, first_alias) local accept_name; if utilities.is_set (last) then last, accept_name = utilities.has_accept_as_written (last); -- remove accept-this-as-written markup when it wraps all of <last> if not accept_name then -- <last> not wrapped in accept-as-written markup name_has_mult_names (last, list_name); -- check for multiple names in the parameter (last only) name_is_numeric (last, list_name); -- check for names that are composed of digits and punctuation name_is_generic (last, last_alias); -- check for names found in the generic names list end end if utilities.is_set (first) then first, accept_name = utilities.has_accept_as_written (first); -- remove accept-this-as-written markup when it wraps all of <first> if not accept_name then -- <first> not wrapped in accept-as-written markup name_is_numeric (first, list_name); -- check for names that are composed of digits and punctuation name_is_generic (first, first_alias); -- check for names found in the generic names list end local wl_type, D = utilities.is_wikilink (first); if 0 ~= wl_type then first = D; utilities.set_message ('err_bad_paramlink', first_alias); end end return last, first; -- done end --[[----------------------< E X T R A C T _ N A M E S >------------------------- Gets name list from the input arguments Searches through args in sequential order to find |lastn= and |firstn= parameters (or their aliases), and their matching link and mask parameters. Stops searching when both |lastn= and |firstn= are not found in args after two sequential attempts: found |last1=, |last2=, and |last3= but doesn't find |last4= and |last5= then the search is done. This function emits an error message when there is a |firstn= without a matching |lastn=. When there are 'holes' in the list of last names, |last1= and |last3= are present but |last2= is missing, an error message is emitted. |lastn= is not required to have a matching |firstn=. When an author or editor parameter contains some form of 'et al.', the 'et al.' is stripped from the parameter and a flag (etal) returned that will cause list_people() to add the static 'et al.' text from Module:Citation/CS1/Configuration. This keeps 'et al.' out of the template's metadata. When this occurs, an error is emitted. ]] local function extract_names(args, list_name) local names = {}; -- table of names local last; -- individual name components local first; local link; local mask; local i = 1; -- loop counter/indexer local n = 1; -- output table indexer local count = 0; -- used to count the number of times we haven't found a |last= (or alias for authors, |editor-last or alias for editors) local etal = false; -- return value set to true when we find some form of et al. in an author parameter local last_alias, first_alias, link_alias; -- selected parameter aliases used in error messaging while true do last, last_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'err_redundant_parameters', i ); -- search through args for name components beginning at 1 first, first_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'err_redundant_parameters', i ); link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ); mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i ); last, etal = name_has_etal (last, etal, false, last_alias); -- find and remove variations on et al. first, etal = name_has_etal (first, etal, false, first_alias); -- find and remove variations on et al. last, first = name_checks (last, first, list_name, last_alias, first_alias); -- multiple names, extraneous annotation, etc. checks if first and not last then -- if there is a firstn without a matching lastn local alias = first_alias:find ('given', 1, true) and 'given' or 'first'; -- get first or given form of the alias utilities.set_message ('err_first_missing_last', { first_alias, -- param name of alias missing its mate first_alias:gsub (alias, {['first'] = 'last', ['given'] = 'surname'}), -- make param name appropriate to the alias form }); -- add this error message elseif not first and not last then -- if both firstn and lastn aren't found, are we done? count = count + 1; -- number of times we haven't found last and first if 2 <= count then -- two missing names and we give up break; -- normal exit or there is a two-name hole in the list; can't tell which end else -- we have last with or without a first local result; link = link_title_ok (link, link_alias, last, last_alias); -- check for improper wiki-markup if first then link = link_title_ok (link, link_alias, first, first_alias); -- check for improper wiki-markup end names[n] = {last = last, first = first, link = link, mask = mask, corporate = false}; -- add this name to our names list (corporate for |vauthors= only) n = n + 1; -- point to next location in the names table if 1 == count then -- if the previous name was missing utilities.set_message ('err_missing_name', {list_name:match ("(%w+)List"):lower(), i - 1}); -- add this error message end count = 0; -- reset the counter, we're looking for two consecutive missing names end i = i + 1; -- point to next args location end return names, etal; -- all done, return our list of names and the etal flag end --[[--------------------------< N A M E _ T A G _ G E T >------------------------------------------------------ attempt to decode |language=<lang_param> and return language name and matching tag; nil else. This function looks for: <lang_param> as a tag in cfg.lang_code_remap{} <lang_param> as a name in cfg.lang_name_remap{} <lang_param> as a name in cfg.mw_languages_by_name_t <lang_param> as a tag in cfg.mw_languages_by_tag_t when those fail, presume that <lang_param> is an IETF-like tag that MediaWiki does not recognize. Strip all script, region, variant, whatever subtags from <lang_param> to leave just a two or three character language tag and look for the new <lang_param> in cfg.mw_languages_by_tag_t{} on success, returns name (in properly capitalized form) and matching tag (in lowercase); on failure returns nil ]] local function name_tag_get (lang_param) local lang_param_lc = mw.ustring.lower (lang_param); -- use lowercase as an index into the various tables local name; local tag; name = cfg.lang_code_remap[lang_param_lc]; -- assume <lang_param_lc> is a tag; attempt to get remapped language name if name then -- when <name>, <lang_param> is a tag for a remapped language name return name, lang_param_lc; -- so return <name> from remap and <lang_param_lc> end tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- still assuming that <lang_param_lc> is a tag; strip script, region, variant subtags name = cfg.lang_code_remap[tag]; -- attempt to get remapped language name with language subtag only if name then -- when <name>, <tag> is a tag for a remapped language name return name, tag; -- so return <name> from remap and <tag> end if cfg.lang_name_remap[lang_param_lc] then -- not a tag, assume <lang_param_lc> is a name; attempt to get remapped language tag return cfg.lang_name_remap[lang_param_lc][1], cfg.lang_name_remap[lang_param_lc][2]; -- for this <lang_param_lc>, return a (possibly) new name and appropriate tag end tag = cfg.mw_languages_by_name_t[lang_param_lc]; -- assume that <lang_param_lc> is a language name; attempt to get its matching tag if tag then return cfg.mw_languages_by_tag_t[tag], tag; -- <lang_param_lc> is a name so return the name from the table and <tag> end name = cfg.mw_languages_by_tag_t[lang_param_lc]; -- assume that <lang_param_lc> is a tag; attempt to get its matching language name if name then return name, lang_param_lc; -- <lang_param_lc> is a tag so return it and <name> end tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- is <lang_param_lc> an IETF-like tag that MediaWiki doesn't recognize? <tag> gets the language subtag; nil else if tag then name = cfg.mw_languages_by_tag_t[tag]; -- attempt to get a language name using the shortened <tag> if name then return name, tag; -- <lang_param_lc> is an unrecognized IETF-like tag so return <name> and language subtag end end end --[[-------------------< L A N G U A G E _ P A R A M E T E R >------------------ Gets language name from a provided two- or three-character ISO 639 code. If a code is recognized by MediaWiki, use the returned name; if not, then use the value that was provided with the language parameter. When |language= contains a recognized language (either code or name), the page is assigned to the category for that code: Category:Norwegian-language sources (no). For valid three-character code languages, the page is assigned to the single category for '639-2' codes: Category:CS1 ISO 639-2 language sources. Languages that are the same as the local wiki are not categorized. MediaWiki does not recognize three-character equivalents of two-character codes: code 'ar' is recognized but code 'ara' is not. This function supports multiple languages in the form |language=nb, French, th where the language names or codes are separated from each other by commas with optional space characters. ]] local function language_parameter (lang) local tag; -- some form of IETF-like language tag; language subtag with optional region, sript, vatiant, etc subtags local lang_subtag; -- ve populates |language= with mostly unecessary region subtags the MediaWiki does not recognize; this is the base language subtag local name; -- the language name local language_list = {}; -- table of language names to be rendered local names_t = {}; -- table made from the value assigned to |language= local this_wiki_name = mw.language.fetchLanguageName (cfg.this_wiki_code, cfg.this_wiki_code); -- get this wiki's language name names_t = mw.text.split (lang, '%s*,%s*'); -- names should be a comma separated list for _, lang in ipairs (names_t) do -- reuse lang here because we don't yet know if lang is a language name or a language tag name, tag = name_tag_get (lang); -- attempt to get name/tag pair for <lang>; <name> has proper capitalization; <tag> is lowercase if utilities.is_set (tag) then lang_subtag = tag:gsub ('^(%a%a%a?)%-.*', '%1'); -- for categorization, strip any IETF-like tags from language tag if cfg.this_wiki_code ~= lang_subtag then -- when the language is not the same as this wiki's language if 2 == lang_subtag:len() then -- and is a two-character tag -- utilities.add_prop_cat ('foreign-lang-source', {name, lang_subtag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization utilities.add_prop_cat ('foreign-lang-source', {name, tag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization else -- or is a recognized language (but has a three-character tag) utilities.add_prop_cat ('foreign-lang-source-2', {lang_subtag}, lang_subtag); -- categorize it differently TODO: support multiple three-character tag categories per cs1|2 template? end elseif cfg.local_lang_cat_enable then -- when the language and this wiki's language are the same and categorization is enabled utilities.add_prop_cat ('local-lang-source', {name, lang_subtag}); -- categorize it end else name = lang; -- return whatever <lang> has so that we show something utilities.set_message ('maint_unknown_lang'); -- add maint category if not already added end table.insert (language_list, name); name = ''; -- so we can reuse it end name = utilities.make_sep_list (#language_list, language_list); if (1 == #language_list) and (lang_subtag == cfg.this_wiki_code) then -- when only one language, find lang name in this wiki lang name; for |language=en-us, 'English' in 'American English' return ''; -- if one language and that language is this wiki's return an empty string (no annotation) end return (" " .. wrap_msg ('language', name)); -- otherwise wrap with '(in ...)' --[[ TODO: should only return blank or name rather than full list so we can clean up the bunched parenthetical elements Language, Type, Format ]] end --[[-----------------------< S E T _ C S _ S T Y L E >-------------------------- Gets the default CS style configuration for the given mode. Returns default separator and either postscript as passed in or the default. In CS1, the default postscript and separator are '.'. In CS2, the default postscript is the empty string and the default separator is ','. ]] local function set_cs_style (postscript, mode) if utilities.is_set(postscript) then -- emit a maintenance message if user postscript is the default cs1 postscript -- we catch the opposite case for cs2 in set_style if mode == 'cs1' and postscript == cfg.presentation['ps_' .. mode] then utilities.set_message ('maint_postscript'); end else postscript = cfg.presentation['ps_' .. mode]; end return cfg.presentation['sep_' .. mode], postscript; end --[[--------------------------< S E T _ S T Y L E >----------------------------- Sets the separator and postscript styles. Checks the |mode= first and the #invoke CitationClass second. Removes the postscript if postscript == none. ]] local function set_style (mode, postscript, cite_class) local sep; if 'cs2' == mode then sep, postscript = set_cs_style (postscript, 'cs2'); elseif 'cs1' == mode then sep, postscript = set_cs_style (postscript, 'cs1'); elseif 'citation' == cite_class then sep, postscript = set_cs_style (postscript, 'cs2'); else sep, postscript = set_cs_style (postscript, 'cs1'); end if cfg.keywords_xlate[postscript:lower()] == 'none' then -- emit a maintenance message if user postscript is the default cs2 postscript -- we catch the opposite case for cs1 in set_cs_style if 'cs2' == mode or 'citation' == cite_class then utilities.set_message ('maint_postscript'); end postscript = ''; end return sep, postscript end --[=[-------------------------< I S _ P D F >----------------------------------- Determines if a URL has the file extension that is one of the PDF file extensions used by [[MediaWiki:Common.css]] when applying the PDF icon to external links. returns true if file extension is one of the recognized extensions, else false ]=] local function is_pdf (url) return url:match ('%.pdf$') or url:match ('%.PDF$') or url:match ('%.pdf[%?#]') or url:match ('%.PDF[%?#]') or url:match ('%.PDF&#035') or url:match ('%.pdf&#035'); end --[[--------------------------< S T Y L E _ F O R M A T >----------------------- Applies CSS style to |format=, |chapter-format=, etc. Also emits an error message if the format parameter does not have a matching URL parameter. If the format parameter is not set and the URL contains a file extension that is recognized as a PDF document by MediaWiki's commons.css, this code will set the format parameter to (PDF) with the appropriate styling. ]] local function style_format (format, url, fmt_param, url_param) if utilities.is_set (format) then format = utilities.wrap_style ('format', format); -- add leading space, parentheses, resize if not utilities.is_set (url) then utilities.set_message ('err_format_missing_url', {fmt_param, url_param}); -- add an error message end elseif is_pdf (url) then -- format is not set so if URL is a PDF file then format = utilities.wrap_style ('format', 'PDF'); -- set format to PDF else format = ''; -- empty string for concatenation end return format; end --[[---------------------< G E T _ D I S P L A Y _ N A M E S >------------------ Returns a number that defines the number of names displayed for author and editor name lists and a Boolean flag to indicate when et al. should be appended to the name list. When the value assigned to |display-xxxxors= is a number greater than or equal to zero, return the number and the previous state of the 'etal' flag (false by default but may have been set to true if the name list contains some variant of the text 'et al.'). When the value assigned to |display-xxxxors= is the keyword 'etal', return a number that is one greater than the number of authors in the list and set the 'etal' flag true. This will cause the list_people() to display all of the names in the name list followed by 'et al.' In all other cases, returns nil and the previous state of the 'etal' flag. inputs: max: A['DisplayAuthors'] or A['DisplayEditors']; a number or some flavor of etal count: #a or #e list_name: 'authors' or 'editors' etal: author_etal or editor_etal ]] local function get_display_names (max, count, list_name, etal, param) if utilities.is_set (max) then if 'etal' == max:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings max = count + 1; -- number of authors + 1 so display all author name plus et al. etal = true; -- overrides value set by extract_names() elseif max:match ('^%d+$') then -- if is a string of numbers max = tonumber (max); -- make it a number if max >= count then -- if |display-xxxxors= value greater than or equal to number of authors/editors utilities.set_message ('err_disp_name', {param, max}); -- add error message max = nil; end else -- not a valid keyword or number utilities.set_message ('err_disp_name', {param, max}); -- add error message max = nil; -- unset; as if |display-xxxxors= had not been set end end return max, etal; end --[[----------< E X T R A _ T E X T _ I N _ P A G E _ C H E C K >--------------- Adds error if |page=, |pages=, |quote-page=, |quote-pages= has what appears to be some form of p. or pp. abbreviation in the first characters of the parameter content. check page for extraneous p, p., pp, pp., pg, pg. at start of parameter value: good pattern: '^P[^%.P%l]' matches when page begins PX or P# but not Px where x and X are letters and # is a digit bad pattern: '^[Pp][PpGg]' matches when page begins pp, pP, Pp, PP, pg, pG, Pg, PG ]] local function extra_text_in_page_check (val, name) if not val:match (cfg.vol_iss_pg_patterns.good_ppattern) then for _, pattern in ipairs (cfg.vol_iss_pg_patterns.bad_ppatterns) do -- spin through the selected sequence table of patterns if val:match (pattern) then -- when a match, error so utilities.set_message ('err_extra_text_pages', name); -- add error message return; -- and done end end end end --[[--------------------------< E X T R A _ T E X T _ I N _ V O L _ I S S _ C H E C K >------------------------ Adds error if |volume= or |issue= has what appears to be some form of redundant 'type' indicator. For |volume=: 'V.', or 'Vol.' (with or without the dot) abbreviations or 'Volume' in the first characters of the parameter content (all case insensitive). 'V' and 'v' (without the dot) are presumed to be roman numerals so are allowed. For |issue=: 'No.', 'I.', 'Iss.' (with or without the dot) abbreviations, or 'Issue' in the first characters of the parameter content (all case insensitive). Single character values ('v', 'i', 'n') allowed when not followed by separator character ('.', ':', '=', or whitespace character) – param values are trimmed of whitespace by MediaWiki before delivered to the module. <val> is |volume= or |issue= parameter value <name> is |volume= or |issue= parameter name for error message <selector> is 'v' for |volume=, 'i' for |issue= sets error message on failure; returns nothing ]] local function extra_text_in_vol_iss_check (val, name, selector) if not utilities.is_set (val) then return; end local patterns = 'v' == selector and cfg.vol_iss_pg_patterns.vpatterns or cfg.vol_iss_pg_patterns.ipatterns; local handler = 'v' == selector and 'err_extra_text_volume' or 'err_extra_text_issue'; val = val:lower(); -- force parameter value to lower case for _, pattern in ipairs (patterns) do -- spin through the selected sequence table of patterns if val:match (pattern) then -- when a match, error so utilities.set_message (handler, name); -- add error message return; -- and done end end end --[=[-------------------------< G E T _ V _ N A M E _ T A B L E >---------------------------------------------- split apart a |vauthors= or |veditors= parameter. This function allows for corporate names, wrapped in doubled parentheses to also have commas; in the old version of the code, the doubled parentheses were included in the rendered citation and in the metadata. Individual author names may be wikilinked |vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.)) ]=] local function get_v_name_table (vparam, output_table, output_link_table) local name_table = mw.text.split(vparam, "%s*,%s*"); -- names are separated by commas local wl_type, label, link; -- wl_type not used here; just a placeholder local i = 1; while name_table[i] do if name_table[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses local name = name_table[i]; i = i + 1; -- bump indexer to next segment while name_table[i] do name = name .. ', ' .. name_table[i]; -- concatenate with previous segments if name_table[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parentheses break; -- and done reassembling so end i = i + 1; -- bump indexer end table.insert (output_table, name); -- and add corporate name to the output table table.insert (output_link_table, ''); -- no wikilink else wl_type, label, link = utilities.is_wikilink (name_table[i]); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]] table.insert (output_table, label); -- add this name if 1 == wl_type then table.insert (output_link_table, label); -- simple wikilink [[D]] else table.insert (output_link_table, link); -- no wikilink or [[L|D]]; add this link if there is one, else empty string end end i = i + 1; end return output_table; end --[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- This function extracts author / editor names from |vauthors= or |veditors= and finds matching |xxxxor-maskn= and |xxxxor-linkn= in args. It then returns a table of assembled names just as extract_names() does. Author / editor names in |vauthors= or |veditors= must be in Vancouver system style. Corporate or institutional names may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance tests, are wrapped in doubled parentheses ((corporate name)) to suppress the format tests. Supports generational suffixes Jr, 2nd, 3rd, 4th–6th. This function sets the Vancouver error when a required comma is missing and when there is a space between an author's initials. ]] local function parse_vauthors_veditors (args, vparam, list_name) local names = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn= local v_name_table = {}; local v_link_table = {}; -- when name is wikilinked, targets go in this table local etal = false; -- return value set to true when we find some form of et al. vauthors parameter local last, first, link, mask, suffix; local corporate = false; vparam, etal = name_has_etal (vparam, etal, true); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period) v_name_table = get_v_name_table (vparam, v_name_table, v_link_table); -- names are separated by commas for i, v_name in ipairs(v_name_table) do first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor local accept_name; v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name> if accept_name then last = v_name; corporate = true; -- flag used in list_people() elseif string.find(v_name, "%s") then if v_name:find('[;%.]') then -- look for commonly occurring punctuation characters; add_vanc_error (cfg.err_msg_supl.punctuation, i); end local lastfirstTable = {} lastfirstTable = mw.text.split(v_name, "%s+") first = table.remove(lastfirstTable); -- removes and returns value of last element in table which should be initials or generational suffix if not mw.ustring.match (first, '^%u+$') then -- mw.ustring here so that later we will catch non-Latin characters suffix = first; -- not initials so assume that whatever we got is a generational suffix first = table.remove(lastfirstTable); -- get what should be the initials from the table end last = table.concat(lastfirstTable, ' ') -- returns a string that is the concatenation of all other names that are not initials and generational suffix if not utilities.is_set (last) then first = ''; -- unset last = v_name; -- last empty because something wrong with first add_vanc_error (cfg.err_msg_supl.name, i); end if mw.ustring.match (last, '%a+%s+%u+%s+%a+') then add_vanc_error (cfg.err_msg_supl['missing comma'], i); -- matches last II last; the case when a comma is missing end if mw.ustring.match (v_name, ' %u %u$') then -- this test is in the wrong place TODO: move or replace with a more appropriate test add_vanc_error (cfg.err_msg_supl.initials, i); -- matches a space between two initials end else last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this? end if utilities.is_set (first) then if not mw.ustring.match (first, "^%u?%u$") then -- first shall contain one or two upper-case letters, nothing else add_vanc_error (cfg.err_msg_supl.initials, i); -- too many initials; mixed case initials (which may be ok Romanization); hyphenated initials end is_good_vanc_name (last, first, suffix, i); -- check first and last before restoring the suffix which may have a non-Latin digit if utilities.is_set (suffix) then first = first .. ' ' .. suffix; -- if there was a suffix concatenate with the initials suffix = ''; -- unset so we don't add this suffix to all subsequent names end else if not corporate then is_good_vanc_name (last, '', nil, i); end end link = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ) or v_link_table[i]; mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i ); names[i] = {last = last, first = first, link = link, mask = mask, corporate = corporate}; -- add this assembled name to our names list end return names, etal; -- all done, return our list of names end --[[--------------------------< S E L E C T _ A U T H O R _ E D I T O R _ S O U R C E >------------------------ Select one of |authors=, |authorn= / |lastn / firstn=, or |vauthors= as the source of the author name list or select one of |editorn= / editor-lastn= / |editor-firstn= or |veditors= as the source of the editor name list. Only one of these appropriate three will be used. The hierarchy is: |authorn= (and aliases) highest and |authors= lowest; |editorn= (and aliases) highest and |veditors= lowest (support for |editors= withdrawn) When looking for |authorn= / |editorn= parameters, test |xxxxor1= and |xxxxor2= (and all of their aliases); stops after the second test which mimicks the test used in extract_names() when looking for a hole in the author name list. There may be a better way to do this, I just haven't discovered what that way is. Emits an error message when more than one xxxxor name source is provided. In this function, vxxxxors = vauthors or veditors; xxxxors = authors as appropriate. ]] local function select_author_editor_source (vxxxxors, xxxxors, args, list_name) local lastfirst = false; if utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice in case we have a |first1= without a |last1=; this ... utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'none', 1 ) or -- ... also catches the case where |first= is used with |vauthors= utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'none', 2 ) or utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'none', 2 ) then lastfirst = true; end if (utilities.is_set (vxxxxors) and true == lastfirst) or -- these are the three error conditions (utilities.is_set (vxxxxors) and utilities.is_set (xxxxors)) or (true == lastfirst and utilities.is_set (xxxxors)) then local err_name; if 'AuthorList' == list_name then -- figure out which name should be used in error message err_name = 'author'; else err_name = 'editor'; end utilities.set_message ('err_redundant_parameters', err_name .. '-name-list parameters'); -- add error message end if true == lastfirst then return 1 end; -- return a number indicating which author name source to use if utilities.is_set (vxxxxors) then return 2 end; if utilities.is_set (xxxxors) then return 3 end; return 1; -- no authors so return 1; this allows missing author name test to run in case there is a first without last end --[[--------------------------< I S _ V A L I D _ P A R A M E T E R _ V A L U E >------------------------------ This function is used to validate a parameter's assigned value for those parameters that have only a limited number of allowable values (yes, y, true, live, dead, etc.). When the parameter value has not been assigned a value (missing or empty in the source template) the function returns the value specified by ret_val. If the parameter value is one of the list of allowed values returns the translated value; else, emits an error message and returns the value specified by ret_val. TODO: explain <invert> ]] local function is_valid_parameter_value (value, name, possible, ret_val, invert) if not utilities.is_set (value) then return ret_val; -- an empty parameter is ok end if (not invert and utilities.in_array (value, possible)) then -- normal; <value> is in <possible> table return cfg.keywords_xlate[value]; -- return translation of parameter keyword elseif invert and not utilities.in_array (value, possible) then -- invert; <value> is not in <possible> table return value; -- return <value> as it is else utilities.set_message ('err_invalid_param_val', {name, value}); -- not an allowed value so add error message return ret_val; end end --[[--------------------------< T E R M I N A T E _ N A M E _ L I S T >---------------------------------------- This function terminates a name list (author, contributor, editor) with a separator character (sepc) and a space when the last character is not a sepc character or when the last three characters are not sepc followed by two closing square brackets (close of a wikilink). When either of these is true, the name_list is terminated with a single space character. ]] local function terminate_name_list (name_list, sepc) if (string.sub (name_list, -3, -1) == sepc .. '. ') then -- if already properly terminated return name_list; -- just return the name list elseif (string.sub (name_list, -1, -1) == sepc) or (string.sub (name_list, -3, -1) == sepc .. ']]') then -- if last name in list ends with sepc char return name_list .. " "; -- don't add another else return name_list .. sepc .. ' '; -- otherwise terminate the name list end end --[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >---------------------------------------- returns the concatenation of the formatted volume and issue parameters as a single string; or formatted volume or formatted issue, or an empty string if neither are set. ]] local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower) if not utilities.is_set (volume) and not utilities.is_set (issue) then return ''; end -- same condition as in format_pages_sheets() local is_journal = 'journal' == cite_class or (utilities.in_array (cite_class, {'citation', 'map', 'interview'}) and 'journal' == origin); local is_numeric_vol = volume and (volume:match ('^[MDCLXVI]+$') or volume:match ('^%d+$')); -- is only uppercase roman numerals or only digits? local is_long_vol = volume and (4 < mw.ustring.len(volume)); -- is |volume= value longer than 4 characters? if volume and (not is_numeric_vol and is_long_vol) then -- when not all digits or Roman numerals, is |volume= longer than 4 characters? utilities.add_prop_cat ('long-vol'); -- yes, add properties cat end if is_journal then -- journal-style formatting local vol = ''; if utilities.is_set (volume) then if is_numeric_vol then -- |volume= value all digits or all uppercase Roman numerals? vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, volume}); -- render in bold face elseif is_long_vol then -- not all digits or Roman numerals; longer than 4 characters? vol = utilities.substitute (cfg.messages['j-vol'], {sepc, utilities.hyphen_to_dash (volume)}); -- not bold else -- four or fewer characters vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, utilities.hyphen_to_dash (volume)}); -- bold end end if utilities.is_set (issue) then return vol .. utilities.substitute (cfg.messages['j-issue'], issue); end return vol; end if 'podcast' == cite_class and utilities.is_set (issue) then return wrap_msg ('issue', {sepc, issue}, lower); end -- all other types of citation if utilities.is_set (volume) and utilities.is_set (issue) then return wrap_msg ('vol-no', {sepc, utilities.hyphen_to_dash (volume), issue}, lower); elseif utilities.is_set (volume) then return wrap_msg ('vol', {sepc, utilities.hyphen_to_dash (volume)}, lower); else return wrap_msg ('issue', {sepc, issue}, lower); end end --[[-------------------------< F O R M A T _ P A G E S _ S H E E T S >----------------------------------------- adds static text to one of |page(s)= or |sheet(s)= values and returns it with all of the others set to empty strings. The return order is: page, pages, sheet, sheets Singular has priority over plural when both are provided. ]] local function format_pages_sheets (page, pages, sheet, sheets, cite_class, origin, sepc, nopp, lower) if 'map' == cite_class then -- only cite map supports sheet(s) as in-source locators if utilities.is_set (sheet) then if 'journal' == origin then return '', '', wrap_msg ('j-sheet', sheet, lower), ''; else return '', '', wrap_msg ('sheet', {sepc, sheet}, lower), ''; end elseif utilities.is_set (sheets) then if 'journal' == origin then return '', '', '', wrap_msg ('j-sheets', sheets, lower); else return '', '', '', wrap_msg ('sheets', {sepc, sheets}, lower); end end end local is_journal = 'journal' == cite_class or (utilities.in_array (cite_class, {'citation', 'map', 'interview'}) and 'journal' == origin); if utilities.is_set (page) then if is_journal then return utilities.substitute (cfg.messages['j-page(s)'], page), '', '', ''; elseif not nopp then return utilities.substitute (cfg.messages['p-prefix'], {sepc, page}), '', '', ''; else return utilities.substitute (cfg.messages['nopp'], {sepc, page}), '', '', ''; end elseif utilities.is_set (pages) then if is_journal then return utilities.substitute (cfg.messages['j-page(s)'], pages), '', '', ''; elseif tonumber(pages) ~= nil and not nopp then -- if pages is only digits, assume a single page number return '', utilities.substitute (cfg.messages['p-prefix'], {sepc, pages}), '', ''; elseif not nopp then return '', utilities.substitute (cfg.messages['pp-prefix'], {sepc, pages}), '', ''; else return '', utilities.substitute (cfg.messages['nopp'], {sepc, pages}), '', ''; end end return '', '', '', ''; -- return empty strings end --[[--------------------------< I N S O U R C E _ L O C _ G E T >---------------------------------------------- returns one of the in-source locators: page, pages, or at. If any of these are interwiki links to Wikisource, returns the label portion of the interwiki-link as plain text for use in COinS. This COinS thing is done because here we convert an interwiki-link to an external link and add an icon span around that; get_coins_pages() doesn't know about the span. TODO: should it? TODO: add support for sheet and sheets?; streamline; TODO: make it so that this function returns only one of the three as the single in-source (the return value assigned to a new name)? ]] local function insource_loc_get (page, page_orig, pages, pages_orig, at) local ws_url, ws_label, coins_pages, L; -- for Wikisource interwiki-links; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?) if utilities.is_set (page) then if utilities.is_set (pages) or utilities.is_set (at) then pages = ''; -- unset the others at = ''; end extra_text_in_page_check (page, page_orig); -- emit error message when |page= value begins with what looks like p., pp., etc. ws_url, ws_label, L = wikisource_url_make (page); -- make ws URL from |page= interwiki link; link portion L becomes tooltip label if ws_url then page = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in page'); -- space char after label to move icon away from in-source text; TODO: a better way to do this? page = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, page}); coins_pages = ws_label; end elseif utilities.is_set (pages) then if utilities.is_set (at) then at = ''; -- unset end extra_text_in_page_check (pages, pages_orig); -- emit error message when |page= value begins with what looks like p., pp., etc. ws_url, ws_label, L = wikisource_url_make (pages); -- make ws URL from |pages= interwiki link; link portion L becomes tooltip label if ws_url then pages = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in pages'); -- space char after label to move icon away from in-source text; TODO: a better way to do this? pages = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, pages}); coins_pages = ws_label; end elseif utilities.is_set (at) then ws_url, ws_label, L = wikisource_url_make (at); -- make ws URL from |at= interwiki link; link portion L becomes tooltip label if ws_url then at = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in at'); -- space char after label to move icon away from in-source text; TODO: a better way to do this? at = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, at}); coins_pages = ws_label; end end return page, pages, at, coins_pages; end --[[--------------------------< I S _ U N I Q U E _ A R C H I V E _ U R L >------------------------------------ add error message when |archive-url= value is same as |url= or chapter-url= (or alias...) value ]] local function is_unique_archive_url (archive, url, c_url, source, date) if utilities.is_set (archive) then if archive == url or archive == c_url then utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}); -- add error message return '', ''; -- unset |archive-url= and |archive-date= because same as |url= or |chapter-url= end end return archive, date; end --[=[-------------------------< A R C H I V E _ U R L _ C H E C K >-------------------------------------------- Check archive.org URLs to make sure they at least look like they are pointing at valid archives and not to the save snapshot URL or to calendar pages. When the archive URL is 'https://web.archive.org/save/' (or http://...) archive.org saves a snapshot of the target page in the URL. That is something that Wikipedia should not allow unwitting readers to do. When the archive.org URL does not have a complete timestamp, archive.org chooses a snapshot according to its own algorithm or provides a calendar 'search' result. [[WP:ELNO]] discourages links to search results. This function looks at the value assigned to |archive-url= and returns empty strings for |archive-url= and |archive-date= and an error message when: |archive-url= holds an archive.org save command URL |archive-url= is an archive.org URL that does not have a complete timestamp (YYYYMMDDhhmmss 14 digits) in the correct place otherwise returns |archive-url= and |archive-date= There are two mostly compatible archive.org URLs: //web.archive.org/<timestamp>... -- the old form //web.archive.org/web/<timestamp>... -- the new form The old form does not support or map to the new form when it contains a display flag. There are four identified flags ('id_', 'js_', 'cs_', 'im_') but since archive.org ignores others following the same form (two letters and an underscore) we don't check for these specific flags but we do check the form. This function supports a preview mode. When the article is rendered in preview mode, this function may return a modified archive URL: for save command errors, return undated wildcard (/*/) for timestamp errors when the timestamp has a wildcard, return the URL unmodified for timestamp errors when the timestamp does not have a wildcard, return with timestamp limited to six digits plus wildcard (/yyyymm*/) ]=] local function archive_url_check (url, date) local err_msg = ''; -- start with the error message empty local path, timestamp, flag; -- portions of the archive.org URL if (not url:match('//web%.archive%.org/')) and (not url:match('//liveweb%.archive%.org/')) then -- also deprecated liveweb Wayback machine URL return url, date; -- not an archive.org archive, return ArchiveURL and ArchiveDate end if url:match('//web%.archive%.org/save/') then -- if a save command URL, we don't want to allow saving of the target page err_msg = cfg.err_msg_supl.save; url = url:gsub ('(//web%.archive%.org)/save/', '%1/*/', 1); -- for preview mode: modify ArchiveURL elseif url:match('//liveweb%.archive%.org/') then err_msg = cfg.err_msg_supl.liveweb; else path, timestamp, flag = url:match('//web%.archive%.org/([^%d]*)(%d+)([^/]*)/'); -- split out some of the URL parts for evaluation if not path then -- malformed in some way; pattern did not match err_msg = cfg.err_msg_supl.timestamp; elseif 14 ~= timestamp:len() then -- path and flag optional, must have 14-digit timestamp here err_msg = cfg.err_msg_supl.timestamp; if '*' ~= flag then local replacement = timestamp:match ('^%d%d%d%d%d%d') or timestamp:match ('^%d%d%d%d'); -- get the first 6 (YYYYMM) or first 4 digits (YYYY) if replacement then -- nil if there aren't at least 4 digits (year) replacement = replacement .. string.rep ('0', 14 - replacement:len()); -- year or yearmo (4 or 6 digits) zero-fill to make 14-digit timestamp url=url:gsub ('(//web%.archive%.org/[^%d]*)%d[^/]*', '%1' .. replacement .. '*', 1) -- for preview, modify ts to 14 digits plus splat for calendar display end end elseif utilities.is_set (path) and 'web/' ~= path then -- older archive URLs do not have the extra 'web/' path element err_msg = cfg.err_msg_supl.path; elseif utilities.is_set (flag) and not utilities.is_set (path) then -- flag not allowed with the old form URL (without the 'web/' path element) err_msg = cfg.err_msg_supl.flag; elseif utilities.is_set (flag) and not flag:match ('%a%a_') then -- flag if present must be two alpha characters and underscore (requires 'web/' path element) err_msg = cfg.err_msg_supl.flag; else return url, date; -- return ArchiveURL and ArchiveDate end end -- if here, something not right so utilities.set_message ('err_archive_url', {err_msg}); -- add error message and if is_preview_mode then return url, date; -- preview mode so return ArchiveURL and ArchiveDate else return '', ''; -- return empty strings for ArchiveURL and ArchiveDate end end --[[--------------------------< P L A C E _ C H E C K >-------------------------------------------------------- check |place=, |publication-place=, |location= to see if these params include digits. This function added because many editors misuse location to specify the in-source location (|page(s)= and |at= are supposed to do that) returns the original parameter value without modification; added maint cat when parameter value contains digits ]] local function place_check (param_val) if not utilities.is_set (param_val) then -- parameter empty or omitted return param_val; -- return that empty state end if mw.ustring.find (param_val, '%d') then -- not empty, are there digits in the parameter value utilities.set_message ('maint_location'); -- yep, add maint cat end return param_val; -- and done end --[[--------------------------< I S _ A R C H I V E D _ C O P Y >---------------------------------------------- compares |title= to 'Archived copy' (placeholder added by bots that can't find proper title); if matches, return true; nil else ]] local function is_archived_copy (title) title = mw.ustring.lower(title); -- switch title to lower case if title:find (cfg.special_case_translation.archived_copy.en) then -- if title is 'Archived copy' return true; elseif cfg.special_case_translation.archived_copy['local'] then if mw.ustring.find (title, cfg.special_case_translation.archived_copy['local']) then -- mw.ustring() because might not be Latin script return true; end end end --[[--------------------------< C I T A T I O N 0 >------------------------------------------------------------ This is the main function doing the majority of the citation formatting. ]] local function citation0( config, args ) --[[ Load Input Parameters The argument_wrapper facilitates the mapping of multiple aliases to single internal variable. ]] local A = argument_wrapper ( args ); local i -- Pick out the relevant fields from the arguments. Different citation templates -- define different field names for the same underlying things. local author_etal; local a = {}; -- authors list from |lastn= / |firstn= pairs or |vauthors= local Authors; local NameListStyle = is_valid_parameter_value (A['NameListStyle'], A:ORIGIN('NameListStyle'), cfg.keywords_lists['name-list-style'], ''); local Collaboration = A['Collaboration']; do -- to limit scope of selected local selected = select_author_editor_source (A['Vauthors'], A['Authors'], args, 'AuthorList'); if 1 == selected then a, author_etal = extract_names (args, 'AuthorList'); -- fetch author list from |authorn= / |lastn= / |firstn=, |author-linkn=, and |author-maskn= elseif 2 == selected then NameListStyle = 'vanc'; -- override whatever |name-list-style= might be a, author_etal = parse_vauthors_veditors (args, args.vauthors, 'AuthorList'); -- fetch author list from |vauthors=, |author-linkn=, and |author-maskn= elseif 3 == selected then Authors = A['Authors']; -- use content of |authors= if 'authors' == A:ORIGIN('Authors') then -- but add a maint cat if the parameter is |authors= utilities.set_message ('maint_authors'); -- because use of this parameter is discouraged; what to do about the aliases is a TODO: end end if utilities.is_set (Collaboration) then author_etal = true; -- so that |display-authors=etal not required end end local editor_etal; local e = {}; -- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors= do -- to limit scope of selected local selected = select_author_editor_source (A['Veditors'], nil, args, 'EditorList'); -- support for |editors= withdrawn if 1 == selected then e, editor_etal = extract_names (args, 'EditorList'); -- fetch editor list from |editorn= / |editor-lastn= / |editor-firstn=, |editor-linkn=, and |editor-maskn= elseif 2 == selected then NameListStyle = 'vanc'; -- override whatever |name-list-style= might be e, editor_etal = parse_vauthors_veditors (args, args.veditors, 'EditorList'); -- fetch editor list from |veditors=, |editor-linkn=, and |editor-maskn= end end local Chapter = A['Chapter']; -- done here so that we have access to |contribution= from |chapter= aliases local Chapter_origin = A:ORIGIN ('Chapter'); local Contribution; -- because contribution is required for contributor(s) if 'contribution' == Chapter_origin then Contribution = Chapter; -- get the name of the contribution end local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (A['Periodical']) then -- |contributor= and |contribution= only supported in book cites c = extract_names (args, 'ContributorList'); -- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn= if 0 < #c then if not utilities.is_set (Contribution) then -- |contributor= requires |contribution= utilities.set_message ('err_contributor_missing_required_param', 'contribution'); -- add missing contribution error message c = {}; -- blank the contributors' table; it is used as a flag later end if 0 == #a then -- |contributor= requires |author= utilities.set_message ('err_contributor_missing_required_param', 'author'); -- add missing author error message c = {}; -- blank the contributors' table; it is used as a flag later end end else -- if not a book cite if utilities.select_one (args, cfg.aliases['ContributorList-Last'], 'err_redundant_parameters', 1 ) then -- are there contributor name list parameters? utilities.set_message ('err_contributor_ignored'); -- add contributor ignored error message end Contribution = nil; -- unset end local Title = A['Title']; local TitleLink = A['TitleLink']; local auto_select = ''; -- default is auto local accept_link; TitleLink, accept_link = utilities.has_accept_as_written (TitleLink, true); -- test for accept-this-as-written markup if (not accept_link) and utilities.in_array (TitleLink, {'none', 'pmc', 'doi'}) then -- check for special keywords auto_select = TitleLink; -- remember selection for later TitleLink = ''; -- treat as if |title-link= would have been empty end TitleLink = link_title_ok (TitleLink, A:ORIGIN ('TitleLink'), Title, 'title'); -- check for wiki-markup in |title-link= or wiki-markup in |title= when |title-link= is set local Section = ''; -- {{cite map}} only; preset to empty string for concatenation if not used if 'map' == config.CitationClass and 'section' == Chapter_origin then Section = A['Chapter']; -- get |section= from |chapter= alias list; |chapter= and the other aliases not supported in {{cite map}} Chapter = ''; -- unset for now; will be reset later from |map= if present end local Periodical = A['Periodical']; local Periodical_origin = ''; if utilities.is_set (Periodical) then Periodical_origin = A:ORIGIN('Periodical'); -- get the name of the periodical parameter local i; Periodical, i = utilities.strip_apostrophe_markup (Periodical); -- strip apostrophe markup so that metadata isn't contaminated if i then -- non-zero when markup was stripped so emit an error message utilities.set_message ('err_apostrophe_markup', {Periodical_origin}); end end if 'mailinglist' == config.CitationClass then -- special case for {{cite mailing list}} if utilities.is_set (Periodical) and utilities.is_set (A ['MailingList']) then -- both set emit an error TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. ' and ' .. utilities.wrap_style ('parameter', 'mailinglist')}); end Periodical = A ['MailingList']; -- error or no, set Periodical to |mailinglist= value because this template is {{cite mailing list}} Periodical_origin = A:ORIGIN('MailingList'); end local ScriptPeriodical = A['ScriptPeriodical']; -- web and news not tested for now because of -- Wikipedia:Administrators%27_noticeboard#Is_there_a_semi-automated_tool_that_could_fix_these_annoying_"Cite_Web"_errors? if not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) then -- 'periodical' templates require periodical parameter -- local p = {['journal'] = 'journal', ['magazine'] = 'magazine', ['news'] = 'newspaper', ['web'] = 'website'}; -- for error message local p = {['journal'] = 'journal', ['magazine'] = 'magazine'}; -- for error message if p[config.CitationClass] then utilities.set_message ('err_missing_periodical', {config.CitationClass, p[config.CitationClass]}); end end local Volume; local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical'); if 'citation' == config.CitationClass then if utilities.is_set (Periodical) then if not utilities.in_array (Periodical_origin, cfg.citation_no_volume_t) then -- {{citation}} does not render |volume= when these parameters are used Volume = A['Volume']; -- but does for all other 'periodicals' end elseif utilities.is_set (ScriptPeriodical) then if 'script-website' ~= ScriptPeriodical_origin then -- {{citation}} does not render volume for |script-website= Volume = A['Volume']; -- but does for all other 'periodicals' end else Volume = A['Volume']; -- and does for non-'periodical' cites end elseif utilities.in_array (config.CitationClass, cfg.templates_using_volume) then -- render |volume= for cs1 according to the configuration settings Volume = A['Volume']; end extra_text_in_vol_iss_check (Volume, A:ORIGIN ('Volume'), 'v'); local Issue; if 'citation' == config.CitationClass then if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, cfg.citation_issue_t) then -- {{citation}} may render |issue= when these parameters are used Issue = utilities.hyphen_to_dash (A['Issue']); end elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then -- conference & map books do not support issue; {{citation}} listed here because included in settings table if not (utilities.in_array (config.CitationClass, {'conference', 'map', 'citation'}) and not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical))) then Issue = utilities.hyphen_to_dash (A['Issue']); end end extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i'); local Page; local Pages; local At; if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then Page = A['Page']; Pages = utilities.hyphen_to_dash (A['Pages']); At = A['At']; end local Edition = A['Edition']; local PublicationPlace = place_check (A['PublicationPlace'], A:ORIGIN('PublicationPlace')); local Place = place_check (A['Place'], A:ORIGIN('Place')); local PublisherName = A['PublisherName']; local PublisherName_origin = A:ORIGIN('PublisherName'); if utilities.is_set (PublisherName) then local i = 0; PublisherName, i = utilities.strip_apostrophe_markup (PublisherName); -- strip apostrophe markup so that metadata isn't contaminated; publisher is never italicized if i then -- non-zero when markup was stripped so emit an error message utilities.set_message ('err_apostrophe_markup', {PublisherName_origin}); end end local Newsgroup = A['Newsgroup']; -- TODO: strip apostrophe markup? local Newsgroup_origin = A:ORIGIN('Newsgroup'); if 'newsgroup' == config.CitationClass then if utilities.is_set (PublisherName) then -- general use parameter |publisher= not allowed in cite newsgroup utilities.set_message ('err_parameter_ignored', {PublisherName_origin}); end PublisherName = nil; -- ensure that this parameter is unset for the time being; will be used again after COinS end local URL = A['URL']; -- TODO: better way to do this for URL, ChapterURL, and MapURL? local UrlAccess = is_valid_parameter_value (A['UrlAccess'], A:ORIGIN('UrlAccess'), cfg.keywords_lists['url-access'], nil); if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then UrlAccess = nil; utilities.set_message ('err_param_access_requires_param', 'url'); end local ChapterURL = A['ChapterURL']; local ChapterUrlAccess = is_valid_parameter_value (A['ChapterUrlAccess'], A:ORIGIN('ChapterUrlAccess'), cfg.keywords_lists['url-access'], nil); if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then ChapterUrlAccess = nil; utilities.set_message ('err_param_access_requires_param', {A:ORIGIN('ChapterUrlAccess'):gsub ('%-access', '')}); end local MapUrlAccess = is_valid_parameter_value (A['MapUrlAccess'], A:ORIGIN('MapUrlAccess'), cfg.keywords_lists['url-access'], nil); if not utilities.is_set (A['MapURL']) and utilities.is_set (MapUrlAccess) then MapUrlAccess = nil; utilities.set_message ('err_param_access_requires_param', {'map-url'}); end local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language local no_tracking_cats = is_valid_parameter_value (A['NoTracking'], A:ORIGIN('NoTracking'), cfg.keywords_lists['yes_true_y'], nil); -- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories if not utilities.is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page if utilities.in_array (this_page.nsText, cfg.uncategorized_namespaces) then no_tracking_cats = "true"; -- set no_tracking_cats end for _, v in ipairs (cfg.uncategorized_subpages) do -- cycle through page name patterns if this_page.text:match (v) then -- test page name against each pattern no_tracking_cats = "true"; -- set no_tracking_cats break; -- bail out if one is found end end end -- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we're at it) utilities.select_one (args, {'page', 'p', 'pp', 'pages', 'at', 'sheet', 'sheets'}, 'err_redundant_parameters'); -- this is a dummy call simply to get the error message and category local coins_pages; Page, Pages, At, coins_pages = insource_loc_get (Page, A:ORIGIN('Page'), Pages, A:ORIGIN('Pages'), At); local NoPP = is_valid_parameter_value (A['NoPP'], A:ORIGIN('NoPP'), cfg.keywords_lists['yes_true_y'], nil); if utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- both |publication-place= and |place= (|location=) allowed if different utilities.add_prop_cat ('location-test'); -- add property cat to evaluate how often PublicationPlace and Place are used together if PublicationPlace == Place then Place = ''; -- unset; don't need both if they are the same end elseif not utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- when only |place= (|location=) is set ... PublicationPlace = Place; -- promote |place= (|location=) to |publication-place end if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same local URL_origin = A:ORIGIN('URL'); -- get name of parameter that holds URL local ChapterURL_origin = A:ORIGIN('ChapterURL'); -- get name of parameter that holds ChapterURL local ScriptChapter = A['ScriptChapter']; local ScriptChapter_origin = A:ORIGIN ('ScriptChapter'); local Format = A['Format']; local ChapterFormat = A['ChapterFormat']; local TransChapter = A['TransChapter']; local TransChapter_origin = A:ORIGIN ('TransChapter'); local TransTitle = A['TransTitle']; local ScriptTitle = A['ScriptTitle']; --[[ Parameter remapping for cite encyclopedia: When the citation has these parameters: |encyclopedia= and |title= then map |title= to |article= and |encyclopedia= to |title= |encyclopedia= and |article= then map |encyclopedia= to |title= |trans-title= maps to |trans-chapter= when |title= is re-mapped |url= maps to |chapter-url= when |title= is remapped All other combinations of |encyclopedia=, |title=, and |article= are not modified ]] local Encyclopedia = A['Encyclopedia']; -- used as a flag by this module and by ~/COinS if utilities.is_set (Encyclopedia) then -- emit error message when Encyclopedia set but template is other than {{cite encyclopedia}} or {{citation}} if 'encyclopaedia' ~= config.CitationClass and 'citation' ~= config.CitationClass then utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('Encyclopedia')}); Encyclopedia = nil; -- unset because not supported by this template end end if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both set emit an error TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', A:ORIGIN ('Encyclopedia')) .. ' and ' .. utilities.wrap_style ('parameter', Periodical_origin)}); end if utilities.is_set (Encyclopedia) then Periodical = Encyclopedia; -- error or no, set Periodical to Encyclopedia; allow periodical without encyclopedia Periodical_origin = A:ORIGIN ('Encyclopedia'); end if utilities.is_set (Periodical) then -- Periodical is set when |encyclopedia= is set if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then if not utilities.is_set (Chapter) then Chapter = Title; -- |encyclopedia= and |title= are set so map |title= to |article= and |encyclopedia= to |title= ScriptChapter = ScriptTitle; ScriptChapter_origin = A:ORIGIN('ScriptTitle') TransChapter = TransTitle; ChapterURL = URL; ChapterURL_origin = URL_origin; ChapterUrlAccess = UrlAccess; if not utilities.is_set (ChapterURL) and utilities.is_set (TitleLink) then Chapter = utilities.make_wikilink (TitleLink, Chapter); end Title = Periodical; ChapterFormat = Format; Periodical = ''; -- redundant so unset TransTitle = ''; URL = ''; Format = ''; TitleLink = ''; ScriptTitle = ''; end elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then -- |title= not set Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= Periodical = ''; -- redundant so unset end end end -- special case for cite techreport. local ID = A['ID']; if (config.CitationClass == "techreport") then -- special case for cite techreport if utilities.is_set (A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue' if not utilities.is_set (ID) then -- can we use ID for the "number"? ID = A['Number']; -- yes, use it else -- ID has a value so emit error message utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. ' and ' .. utilities.wrap_style ('parameter', 'number')}); end end end -- Account for the oddity that is {{cite conference}}, before generation of COinS data. local ChapterLink -- = A['ChapterLink']; -- deprecated as a parameter but still used internally by cite episode local Conference = A['Conference']; local BookTitle = A['BookTitle']; local TransTitle_origin = A:ORIGIN ('TransTitle'); if 'conference' == config.CitationClass then if utilities.is_set (BookTitle) then Chapter = Title; Chapter_origin = 'title'; -- ChapterLink = TitleLink; -- |chapter-link= is deprecated ChapterURL = URL; ChapterUrlAccess = UrlAccess; ChapterURL_origin = URL_origin; URL_origin = ''; ChapterFormat = Format; TransChapter = TransTitle; TransChapter_origin = TransTitle_origin; Title = BookTitle; Format = ''; -- TitleLink = ''; TransTitle = ''; URL = ''; end elseif 'speech' ~= config.CitationClass then Conference = ''; -- not cite conference or cite speech so make sure this is empty string end -- CS1/2 mode local Mode = is_valid_parameter_value (A['Mode'], A:ORIGIN('Mode'), cfg.keywords_lists['mode'], ''); -- separator character and postscript local sepc, PostScript = set_style (Mode:lower(), A['PostScript'], config.CitationClass); -- controls capitalization of certain static text local use_lowercase = ( sepc == ',' ); -- cite map oddities local Cartography = ""; local Scale = ""; local Sheet = A['Sheet'] or ''; local Sheets = A['Sheets'] or ''; if config.CitationClass == "map" then if utilities.is_set (Chapter) then --TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. ' and ' .. utilities.wrap_style ('parameter', Chapter_origin)}); -- add error message end Chapter = A['Map']; Chapter_origin = A:ORIGIN('Map'); ChapterURL = A['MapURL']; ChapterURL_origin = A:ORIGIN('MapURL'); TransChapter = A['TransMap']; ScriptChapter = A['ScriptMap'] ScriptChapter_origin = A:ORIGIN('ScriptMap') ChapterUrlAccess = MapUrlAccess; ChapterFormat = A['MapFormat']; Cartography = A['Cartography']; if utilities.is_set ( Cartography ) then Cartography = sepc .. " " .. wrap_msg ('cartography', Cartography, use_lowercase); end Scale = A['Scale']; if utilities.is_set ( Scale ) then Scale = sepc .. " " .. Scale; end end -- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data. local Series = A['Series']; if 'episode' == config.CitationClass or 'serial' == config.CitationClass then local SeriesLink = A['SeriesLink']; SeriesLink = link_title_ok (SeriesLink, A:ORIGIN ('SeriesLink'), Series, 'series'); -- check for wiki-markup in |series-link= or wiki-markup in |series= when |series-link= is set local Network = A['Network']; local Station = A['Station']; local s, n = {}, {}; -- do common parameters first if utilities.is_set (Network) then table.insert(n, Network); end if utilities.is_set (Station) then table.insert(n, Station); end ID = table.concat(n, sepc .. ' '); if 'episode' == config.CitationClass then -- handle the oddities that are strictly {{cite episode}} local Season = A['Season']; local SeriesNumber = A['SeriesNumber']; if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then -- these are mutually exclusive so if both are set TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. ' and ' .. utilities.wrap_style ('parameter', 'seriesno')}); -- add error message SeriesNumber = ''; -- unset; prefer |season= over |seriesno= end -- assemble a table of parts concatenated later into Series if utilities.is_set (Season) then table.insert(s, wrap_msg ('season', Season, use_lowercase)); end if utilities.is_set (SeriesNumber) then table.insert(s, wrap_msg ('seriesnum', SeriesNumber, use_lowercase)); end if utilities.is_set (Issue) then table.insert(s, wrap_msg ('episode', Issue, use_lowercase)); end Issue = ''; -- unset because this is not a unique parameter Chapter = Title; -- promote title parameters to chapter ScriptChapter = ScriptTitle; ScriptChapter_origin = A:ORIGIN('ScriptTitle'); ChapterLink = TitleLink; -- alias |episode-link= TransChapter = TransTitle; ChapterURL = URL; ChapterUrlAccess = UrlAccess; ChapterURL_origin = URL_origin; ChapterFormat = Format; Title = Series; -- promote series to title TitleLink = SeriesLink; Series = table.concat(s, sepc .. ' '); -- this is concatenation of season, seriesno, episode number if utilities.is_set (ChapterLink) and not utilities.is_set (ChapterURL) then -- link but not URL Chapter = utilities.make_wikilink (ChapterLink, Chapter); elseif utilities.is_set (ChapterLink) and utilities.is_set (ChapterURL) then -- if both are set, URL links episode; Series = utilities.make_wikilink (ChapterLink, Series); end URL = ''; -- unset TransTitle = ''; ScriptTitle = ''; Format = ''; else -- now oddities that are cite serial Issue = ''; -- unset because this parameter no longer supported by the citation/core version of cite serial Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday? if utilities.is_set (Series) and utilities.is_set (SeriesLink) then Series = utilities.make_wikilink (SeriesLink, Series); end Series = utilities.wrap_style ('italic-title', Series); -- series is italicized end end -- end of {{cite episode}} stuff -- handle type parameter for those CS1 citations that have default values local TitleType = A['TitleType']; local Degree = A['Degree']; if utilities.in_array (config.CitationClass, {'AV-media-notes', 'interview', 'mailinglist', 'map', 'podcast', 'pressrelease', 'report', 'speech', 'techreport', 'thesis'}) then TitleType = set_titletype (config.CitationClass, TitleType); if utilities.is_set (Degree) and "Thesis" == TitleType then -- special case for cite thesis TitleType = Degree .. ' ' .. cfg.title_types ['thesis']:lower(); end end if utilities.is_set (TitleType) then -- if type parameter is specified TitleType = utilities.substitute ( cfg.messages['type'], TitleType); -- display it in parentheses -- TODO: Hack on TitleType to fix bunched parentheses problem end -- legacy: promote PublicationDate to Date if neither Date nor Year are set. local Date = A['Date']; local Date_origin; -- to hold the name of parameter promoted to Date; required for date error messaging local PublicationDate = A['PublicationDate']; local Year = A['Year']; if not utilities.is_set (Date) then Date = Year; -- promote Year to Date Year = nil; -- make nil so Year as empty string isn't used for CITEREF if not utilities.is_set (Date) and utilities.is_set (PublicationDate) then -- use PublicationDate when |date= and |year= are not set Date = PublicationDate; -- promote PublicationDate to Date PublicationDate = ''; -- unset, no longer needed Date_origin = A:ORIGIN('PublicationDate'); -- save the name of the promoted parameter else Date_origin = A:ORIGIN('Year'); -- save the name of the promoted parameter end else Date_origin = A:ORIGIN('Date'); -- not a promotion; name required for error messaging end if PublicationDate == Date then PublicationDate = ''; end -- if PublicationDate is same as Date, don't display in rendered citation --[[ Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where we get the date used in the metadata. Date validation supporting code is in Module:Citation/CS1/Date_validation ]] local DF = is_valid_parameter_value (A['DF'], A:ORIGIN('DF'), cfg.keywords_lists['df'], ''); if not utilities.is_set (DF) then DF = cfg.global_df; -- local |df= if present overrides global df set by {{use xxx date}} template end local ArchiveURL; local ArchiveDate; local ArchiveFormat = A['ArchiveFormat']; ArchiveURL, ArchiveDate = archive_url_check (A['ArchiveURL'], A['ArchiveDate']) ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, 'archive-format', 'archive-url'); ArchiveURL, ArchiveDate = is_unique_archive_url (ArchiveURL, URL, ChapterURL, A:ORIGIN('ArchiveURL'), ArchiveDate); -- add error message when URL or ChapterURL == ArchiveURL local AccessDate = A['AccessDate']; local LayDate = A['LayDate']; local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification local DoiBroken = A['DoiBroken']; local Embargo = A['Embargo']; local anchor_year; -- used in the CITEREF identifier do -- create defined block to contain local variables error_message, date_parameters_list, mismatch local error_message = ''; -- AirDate has been promoted to Date so not necessary to check it local date_parameters_list = { ['access-date'] = {val = AccessDate, name = A:ORIGIN ('AccessDate')}, ['archive-date'] = {val = ArchiveDate, name = A:ORIGIN ('ArchiveDate')}, ['date'] = {val = Date, name = Date_origin}, ['doi-broken-date'] = {val = DoiBroken, name = A:ORIGIN ('DoiBroken')}, ['pmc-embargo-date'] = {val = Embargo, name = A:ORIGIN ('Embargo')}, ['lay-date'] = {val = LayDate, name = A:ORIGIN ('LayDate')}, ['publication-date'] = {val = PublicationDate, name = A:ORIGIN ('PublicationDate')}, ['year'] = {val = Year, name = A:ORIGIN ('Year')}, }; local error_list = {}; anchor_year, Embargo = validation.dates(date_parameters_list, COinS_date, error_list); -- start temporary Julian / Gregorian calendar uncertainty categorization if COinS_date.inter_cal_cat then utilities.add_prop_cat ('jul-greg-uncertainty'); end -- end temporary Julian / Gregorian calendar uncertainty categorization if utilities.is_set (Year) and utilities.is_set (Date) then -- both |date= and |year= not normally needed; validation.year_date_check (Year, A:ORIGIN ('Year'), Date, A:ORIGIN ('Date'), error_list); end if 0 == #error_list then -- error free dates only; 0 when error_list is empty local modified = false; -- flag if utilities.is_set (DF) then -- if we need to reformat dates modified = validation.reformat_dates (date_parameters_list, DF); -- reformat to DF format, use long month names if appropriate end if true == validation.date_hyphen_to_dash (date_parameters_list) then -- convert hyphens to dashes where appropriate modified = true; utilities.set_message ('maint_date_format'); -- hyphens were converted so add maint category end -- for those wikis that can and want to have English date names translated to the local language; not supported at en.wiki if cfg.date_name_auto_xlate_enable and validation.date_name_xlate (date_parameters_list, cfg.date_digit_auto_xlate_enable ) then utilities.set_message ('maint_date_auto_xlated'); -- add maint cat modified = true; end if modified then -- if the date_parameters_list values were modified AccessDate = date_parameters_list['access-date'].val; -- overwrite date holding parameters with modified values ArchiveDate = date_parameters_list['archive-date'].val; Date = date_parameters_list['date'].val; DoiBroken = date_parameters_list['doi-broken-date'].val; LayDate = date_parameters_list['lay-date'].val; PublicationDate = date_parameters_list['publication-date'].val; end else utilities.set_message ('err_bad_date', {utilities.make_sep_list (#error_list, error_list)}); -- add this error message end end -- end of do local ID_list = {}; -- sequence table of rendered identifiers local ID_list_coins = {}; -- table of identifiers and their values from args; key is same as cfg.id_handlers's key local Class = A['Class']; -- arxiv class identifier local ID_support = { {A['ASINTLD'], 'ASIN', 'err_asintld_missing_asin', A:ORIGIN ('ASINTLD')}, {DoiBroken, 'DOI', 'err_doibroken_missing_doi', A:ORIGIN ('DoiBroken')}, {Embargo, 'PMC', 'err_embargo_missing_pmc', A:ORIGIN ('Embargo')}, } ID_list, ID_list_coins = identifiers.identifier_lists_get (args, {DoiBroken = DoiBroken, ASINTLD = A['ASINTLD'], Embargo = Embargo, Class = Class}, ID_support); -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data. if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then if not utilities.is_set (ID_list_coins[config.CitationClass:upper()]) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv= & |citeseerx= required for their templates utilities.set_message ('err_' .. config.CitationClass .. '_missing'); -- add error message end Periodical = ({['arxiv'] = 'arXiv', ['biorxiv'] = 'bioRxiv', ['citeseerx'] = 'CiteSeerX', ['ssrn'] = 'Social Science Research Network'})[config.CitationClass]; end -- Link the title of the work if no |url= was provided, but we have a |pmc= or a |doi= with |doi-access=free if config.CitationClass == "journal" and not utilities.is_set (URL) and not utilities.is_set (TitleLink) and not utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) then -- TODO: remove 'none' once existing citations have been switched to 'off', so 'none' can be used as token for "no title" instead if 'none' ~= cfg.keywords_xlate[auto_select] then -- if auto-linking not disabled if identifiers.auto_link_urls[auto_select] then -- manual selection URL = identifiers.auto_link_urls[auto_select]; -- set URL to be the same as identifier's external link URL_origin = cfg.id_handlers[auto_select:upper()].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title= elseif identifiers.auto_link_urls['pmc'] then -- auto-select PMC URL = identifiers.auto_link_urls['pmc']; -- set URL to be the same as the PMC external link if not embargoed URL_origin = cfg.id_handlers['PMC'].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title= elseif identifiers.auto_link_urls['doi'] then -- auto-select DOI URL = identifiers.auto_link_urls['doi']; URL_origin = cfg.id_handlers['DOI'].parameters[1]; end end if utilities.is_set (URL) then -- set when using an identifier-created URL if utilities.is_set (AccessDate) then -- |access-date= requires |url=; identifier-created URL is not |url= utilities.set_message ('err_accessdate_missing_url'); -- add an error message AccessDate = ''; -- unset end if utilities.is_set (ArchiveURL) then -- |archive-url= requires |url=; identifier-created URL is not |url= utilities.set_message ('err_archive_missing_url'); -- add an error message ArchiveURL = ''; -- unset end end end -- At this point fields may be nil if they weren't specified in the template use. We can use that fact. -- Test if citation has no title if not utilities.is_set (Title) and not utilities.is_set (TransTitle) and not utilities.is_set (ScriptTitle) then -- has special case for cite episode utilities.set_message ('err_citation_missing_title', {'episode' == config.CitationClass and 'series' or 'title'}); end if utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) and utilities.in_array (config.CitationClass, {'journal', 'citation'}) and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and ('journal' == Periodical_origin or 'script-journal' == ScriptPeriodical_origin) then -- special case for journal cites Title = ''; -- set title to empty string utilities.set_message ('maint_untitled'); -- add maint cat end -- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information. -- handle the oddity that is cite encyclopedia and {{citation |encyclopedia=something}}. Here we presume that -- when Periodical, Title, and Chapter are all set, then Periodical is the book (encyclopedia) title, Title -- is the article title, and Chapter is a section within the article. So, we remap local coins_chapter = Chapter; -- default assuming that remapping not required local coins_title = Title; -- et tu if 'encyclopaedia' == config.CitationClass or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then if utilities.is_set (Chapter) and utilities.is_set (Title) and utilities.is_set (Periodical) then -- if all are used then coins_chapter = Title; -- remap coins_title = Periodical; end end local coins_author = a; -- default for coins rft.au if 0 < #c then -- but if contributor list coins_author = c; -- use that instead end local QuotePage = A['QuotePage']; local QuotePages = utilities.hyphen_to_dash (A['QuotePages']); -- this is the function call to COinS() local OCinSoutput = metadata.COinS({ ['Periodical'] = utilities.strip_apostrophe_markup (Periodical), -- no markup in the metadata ['Encyclopedia'] = Encyclopedia, -- just a flag; content ignored by ~/COinS ['Chapter'] = metadata.make_coins_title (coins_chapter, ScriptChapter), -- Chapter and ScriptChapter stripped of bold / italic / accept-as-written markup ['Degree'] = Degree; -- cite thesis only ['Title'] = metadata.make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic / accept-as-written markup ['PublicationPlace'] = PublicationPlace, ['Date'] = COinS_date.rftdate, -- COinS_date has correctly formatted date if Date is valid; ['Season'] = COinS_date.rftssn, ['Quarter'] = COinS_date.rftquarter, ['Chron'] = COinS_date.rftchron or (not COinS_date.rftdate and Date) or '', -- chron but if not set and invalid date format use Date; keep this last bit? ['Series'] = Series, ['Volume'] = Volume, ['Issue'] = Issue, ['Pages'] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)), -- pages stripped of external links ['Edition'] = Edition, ['PublisherName'] = PublisherName or Newsgroup, -- any apostrophe markup already removed from PublisherName ['URL'] = first_set ({ChapterURL, URL}, 2), ['Authors'] = coins_author, ['ID_list'] = ID_list_coins, ['RawPage'] = this_page.prefixedText, }, config.CitationClass); -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, and {{cite ssrn}} AFTER generation of COinS data. if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then -- we have set rft.jtitle in COinS to arXiv, bioRxiv, CiteSeerX, or ssrn now unset so it isn't displayed Periodical = ''; -- periodical not allowed in these templates; if article has been published, use cite journal end -- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text if 'newsgroup' == config.CitationClass and utilities.is_set (Newsgroup) then PublisherName = utilities.substitute (cfg.messages['newsgroup'], external_link( 'news:' .. Newsgroup, Newsgroup, Newsgroup_origin, nil )); end local Editors; local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list local Contributors; -- assembled contributors name list local contributor_etal; local Translators; -- assembled translators name list local translator_etal; local t = {}; -- translators list from |translator-lastn= / translator-firstn= pairs t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn= local Interviewers; local interviewers_list = {}; interviewers_list = extract_names (args, 'InterviewerList'); -- process preferred interviewers parameters local interviewer_etal; -- Now perform various field substitutions. -- We also add leading spaces and surrounding markup and punctuation to the -- various parts of the citation, but only when they are non-nil. do local last_first_list; local control = { format = NameListStyle, -- empty string or 'vanc' maximum = nil, -- as if display-authors or display-editors not set mode = Mode }; do -- do editor name list first because the now unsupported coauthors used to modify control table control.maximum , editor_etal = get_display_names (A['DisplayEditors'], #e, 'editors', editor_etal, A:ORIGIN ('DisplayEditors')); Editors, EditorCount = list_people (control, e, editor_etal); if 1 == EditorCount and (true == editor_etal or 1 < #e) then -- only one editor displayed but includes etal then EditorCount = 2; -- spoof to display (eds.) annotation end end do -- now do interviewers control.maximum, interviewer_etal = get_display_names (A['DisplayInterviewers'], #interviewers_list, 'interviewers', interviewer_etal, A:ORIGIN ('DisplayInterviewers')); Interviewers = list_people (control, interviewers_list, interviewer_etal); end do -- now do translators control.maximum, translator_etal = get_display_names (A['DisplayTranslators'], #t, 'translators', translator_etal, A:ORIGIN ('DisplayTranslators')); Translators = list_people (control, t, translator_etal); end do -- now do contributors control.maximum, contributor_etal = get_display_names (A['DisplayContributors'], #c, 'contributors', contributor_etal, A:ORIGIN ('DisplayContributors')); Contributors = list_people (control, c, contributor_etal); end do -- now do authors control.maximum, author_etal = get_display_names (A['DisplayAuthors'], #a, 'authors', author_etal, A:ORIGIN ('DisplayAuthors')); last_first_list = list_people (control, a, author_etal); if utilities.is_set (Authors) then Authors, author_etal = name_has_etal (Authors, author_etal, false, 'authors'); -- find and remove variations on et al. if author_etal then Authors = Authors .. ' ' .. cfg.messages['et al']; -- add et al. to authors parameter end else Authors = last_first_list; -- either an author name list or an empty string end end -- end of do if utilities.is_set (Authors) and utilities.is_set (Collaboration) then Authors = Authors .. ' (' .. Collaboration .. ')'; -- add collaboration after et al. end end local ConferenceFormat = A['ConferenceFormat']; local ConferenceURL = A['ConferenceURL']; ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, 'conference-format', 'conference-url'); Format = style_format (Format, URL, 'format', 'url'); -- special case for chapter format so no error message or cat when chapter not supported if not (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia))) then ChapterFormat = style_format (ChapterFormat, ChapterURL, 'chapter-format', 'chapter-url'); end if not utilities.is_set (URL) then if utilities.in_array (config.CitationClass, {"web", "podcast", "mailinglist"}) or -- |url= required for cite web, cite podcast, and cite mailinglist ('citation' == config.CitationClass and ('website' == Periodical_origin or 'script-website' == ScriptPeriodical_origin)) then -- and required for {{citation}} with |website= or |script-website= utilities.set_message ('err_cite_web_url'); end -- do we have |accessdate= without either |url= or |chapter-url=? if utilities.is_set (AccessDate) and not utilities.is_set (ChapterURL) then -- ChapterURL may be set when URL is not set; utilities.set_message ('err_accessdate_missing_url'); AccessDate = ''; end end local UrlStatus = is_valid_parameter_value (A['UrlStatus'], A:ORIGIN('UrlStatus'), cfg.keywords_lists['url-status'], ''); local OriginalURL local OriginalURL_origin local OriginalFormat local OriginalAccess; UrlStatus = UrlStatus:lower(); -- used later when assembling archived text if utilities.is_set ( ArchiveURL ) then if utilities.is_set (ChapterURL) then -- if chapter-url= is set apply archive url to it OriginalURL = ChapterURL; -- save copy of source chapter's url for archive text OriginalURL_origin = ChapterURL_origin; -- name of |chapter-url= parameter for error messages OriginalFormat = ChapterFormat; -- and original |chapter-format= if 'live' ~= UrlStatus then ChapterURL = ArchiveURL -- swap-in the archive's URL ChapterURL_origin = A:ORIGIN('ArchiveURL') -- name of |archive-url= parameter for error messages ChapterFormat = ArchiveFormat or ''; -- swap in archive's format ChapterUrlAccess = nil; -- restricted access levels do not make sense for archived URLs end elseif utilities.is_set (URL) then OriginalURL = URL; -- save copy of original source URL OriginalURL_origin = URL_origin; -- name of URL parameter for error messages OriginalFormat = Format; -- and original |format= OriginalAccess = UrlAccess; if 'live' ~= UrlStatus then -- if URL set then |archive-url= applies to it URL = ArchiveURL -- swap-in the archive's URL URL_origin = A:ORIGIN('ArchiveURL') -- name of archive URL parameter for error messages Format = ArchiveFormat or ''; -- swap in archive's format UrlAccess = nil; -- restricted access levels do not make sense for archived URLs end end elseif utilities.is_set (UrlStatus) then -- if |url-status= is set when |archive-url= is not set utilities.set_message ('maint_url_status'); -- add maint cat end if utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or -- if any of the 'periodical' cites except encyclopedia ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) then local chap_param; if utilities.is_set (Chapter) then -- get a parameter name from one of these chapter related meta-parameters chap_param = A:ORIGIN ('Chapter') elseif utilities.is_set (TransChapter) then chap_param = A:ORIGIN ('TransChapter') elseif utilities.is_set (ChapterURL) then chap_param = A:ORIGIN ('ChapterURL') elseif utilities.is_set (ScriptChapter) then chap_param = ScriptChapter_origin; else utilities.is_set (ChapterFormat) chap_param = A:ORIGIN ('ChapterFormat') end if utilities.is_set (chap_param) then -- if we found one utilities.set_message ('err_chapter_ignored', {chap_param}); -- add error message Chapter = ''; -- and set them to empty string to be safe with concatenation TransChapter = ''; ChapterURL = ''; ScriptChapter = ''; ChapterFormat = ''; end else -- otherwise, format chapter / article title local no_quotes = false; -- default assume that we will be quoting the chapter parameter value if utilities.is_set (Contribution) and 0 < #c then -- if this is a contribution with contributor(s) if utilities.in_array (Contribution:lower(), cfg.keywords_lists.contribution) then -- and a generic contribution title no_quotes = true; -- then render it unquoted end end Chapter = format_chapter_title (ScriptChapter, ScriptChapter_origin, Chapter, Chapter_origin, TransChapter, TransChapter_origin, ChapterURL, ChapterURL_origin, no_quotes, ChapterUrlAccess); -- Contribution is also in Chapter if utilities.is_set (Chapter) then Chapter = Chapter .. ChapterFormat ; if 'map' == config.CitationClass and utilities.is_set (TitleType) then Chapter = Chapter .. ' ' .. TitleType; -- map annotation here; not after title end Chapter = Chapter .. sepc .. ' '; elseif utilities.is_set (ChapterFormat) then -- |chapter= not set but |chapter-format= is so ... Chapter = ChapterFormat .. sepc .. ' '; -- ... ChapterFormat has error message, we want to see it end end -- Format main title local plain_title = false; local accept_title; Title, accept_title = utilities.has_accept_as_written (Title, true); -- remove accept-this-as-written markup when it wraps all of <Title> if accept_title and ('' == Title) then -- only support forced empty for now "(())" Title = cfg.messages['notitle']; -- replace by predefined "No title" message -- TODO: utilities.set_message ( 'err_redundant_parameters', ...); -- issue proper error message instead of muting ScriptTitle = ''; -- just mute for now TransTitle = ''; -- just mute for now plain_title = true; -- suppress text decoration for descriptive title utilities.set_message ('maint_untitled'); -- add maint cat end if not accept_title then -- <Title> not wrapped in accept-as-written markup if '...' == Title:sub (-3) then -- if ellipsis is the last three characters of |title= Title = Title:gsub ('(%.%.%.)%.+$', '%1'); -- limit the number of dots to three elseif not mw.ustring.find (Title, '%.%s*%a%.$') and -- end of title is not a 'dot-(optional space-)letter-dot' initialism ... not mw.ustring.find (Title, '%s+%a%.$') then -- ...and not a 'space-letter-dot' initial (''Allium canadense'' L.) Title = mw.ustring.gsub(Title, '%' .. sepc .. '$', ''); -- remove any trailing separator character; sepc and ms.ustring() here for languages that use multibyte separator characters end if utilities.is_set (ArchiveURL) and is_archived_copy (Title) then utilities.set_message ('maint_archived_copy'); -- add maintenance category before we modify the content of Title end if is_generic ('generic_titles', Title) then utilities.set_message ('err_generic_title'); -- set an error message end end if (not plain_title) and (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) or ('map' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)))) then -- special case for cite map when the map is in a periodical treat as an article Title = kern_quotes (Title); -- if necessary, separate title's leading and trailing quote marks from module provided quote marks Title = utilities.wrap_style ('quoted-title', Title); Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); elseif plain_title or ('report' == config.CitationClass) then -- no styling for cite report and descriptive titles (otherwise same as above) Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); -- for cite report, use this form for trans-title else Title = utilities.wrap_style ('italic-title', Title); Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped TransTitle = utilities.wrap_style ('trans-italic-title', TransTitle); end if utilities.is_set (TransTitle) then if utilities.is_set (Title) then TransTitle = " " .. TransTitle; else utilities.set_message ('err_trans_missing_title', {'title'}); end end if utilities.is_set (Title) then -- TODO: is this the right place to be making Wikisource URLs? if utilities.is_set (TitleLink) and utilities.is_set (URL) then utilities.set_message ('err_wikilink_in_url'); -- set an error message because we can't have both TitleLink = ''; -- unset end if not utilities.is_set (TitleLink) and utilities.is_set (URL) then Title = external_link (URL, Title, URL_origin, UrlAccess) .. TransTitle .. Format; URL = ''; -- unset these because no longer needed Format = ""; elseif utilities.is_set (TitleLink) and not utilities.is_set (URL) then local ws_url; ws_url = wikisource_url_make (TitleLink); -- ignore ws_label return; not used here if ws_url then Title = external_link (ws_url, Title .. '&nbsp;', 'ws link in title-link'); -- space char after Title to move icon away from italic text; TODO: a better way to do this? Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], TitleLink, Title}); Title = Title .. TransTitle; else Title = utilities.make_wikilink (TitleLink, Title) .. TransTitle; end else local ws_url, ws_label, L; -- Title has italic or quote markup by the time we get here which causes is_wikilink() to return 0 (not a wikilink) ws_url, ws_label, L = wikisource_url_make (Title:gsub('^[\'"]*(.-)[\'"]*$', '%1')); -- make ws URL from |title= interwiki link (strip italic or quote markup); link portion L becomes tooltip label if ws_url then Title = Title:gsub ('%b[]', ws_label); -- replace interwiki link with ws_label to retain markup Title = external_link (ws_url, Title .. '&nbsp;', 'ws link in title'); -- space char after Title to move icon away from italic text; TODO: a better way to do this? Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, Title}); Title = Title .. TransTitle; else Title = Title .. TransTitle; end end else Title = TransTitle; end if utilities.is_set (Place) then Place = " " .. wrap_msg ('written', Place, use_lowercase) .. sepc .. " "; end local ConferenceURL_origin = A:ORIGIN('ConferenceURL'); -- get name of parameter that holds ConferenceURL if utilities.is_set (Conference) then if utilities.is_set (ConferenceURL) then Conference = external_link( ConferenceURL, Conference, ConferenceURL_origin, nil ); end Conference = sepc .. " " .. Conference .. ConferenceFormat; elseif utilities.is_set (ConferenceURL) then Conference = sepc .. " " .. external_link( ConferenceURL, nil, ConferenceURL_origin, nil ); end local Position = ''; if not utilities.is_set (Position) then local Minutes = A['Minutes']; local Time = A['Time']; if utilities.is_set (Minutes) then if utilities.is_set (Time) then --TODO: make a function for this and similar? utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. ' and ' .. utilities.wrap_style ('parameter', 'time')}); end Position = " " .. Minutes .. " " .. cfg.messages['minutes']; else if utilities.is_set (Time) then local TimeCaption = A['TimeCaption'] if not utilities.is_set (TimeCaption) then TimeCaption = cfg.messages['event']; if sepc ~= '.' then TimeCaption = TimeCaption:lower(); end end Position = " " .. TimeCaption .. " " .. Time; end end else Position = " " .. Position; At = ''; end Page, Pages, Sheet, Sheets = format_pages_sheets (Page, Pages, Sheet, Sheets, config.CitationClass, Periodical_origin, sepc, NoPP, use_lowercase); At = utilities.is_set (At) and (sepc .. " " .. At) or ""; Position = utilities.is_set (Position) and (sepc .. " " .. Position) or ""; if config.CitationClass == 'map' then local Sections = A['Sections']; -- Section (singular) is an alias of Chapter so set earlier local Inset = A['Inset']; if utilities.is_set ( Inset ) then Inset = sepc .. " " .. wrap_msg ('inset', Inset, use_lowercase); end if utilities.is_set ( Sections ) then Section = sepc .. " " .. wrap_msg ('sections', Sections, use_lowercase); elseif utilities.is_set ( Section ) then Section = sepc .. " " .. wrap_msg ('section', Section, use_lowercase); end At = At .. Inset .. Section; end local Others = A['Others']; if utilities.is_set (Others) and 0 == #a and 0 == #e then -- add maint cat when |others= has value and used without |author=, |editor= if config.CitationClass == "AV-media-notes" or config.CitationClass == "audio-visual" then -- special maint for AV/M which has a lot of 'false' positives right now utilities.set_message ('maint_others_avm') else utilities.set_message ('maint_others'); end end Others = utilities.is_set (Others) and (sepc .. " " .. Others) or ""; if utilities.is_set (Translators) then Others = safe_join ({sepc .. ' ', wrap_msg ('translated', Translators, use_lowercase), Others}, sepc); end if utilities.is_set (Interviewers) then Others = safe_join ({sepc .. ' ', wrap_msg ('interview', Interviewers, use_lowercase), Others}, sepc); end local TitleNote = A['TitleNote']; TitleNote = utilities.is_set (TitleNote) and (sepc .. " " .. TitleNote) or ""; if utilities.is_set (Edition) then if Edition:match ('%f[%a][Ee]d%n?%.?$') or Edition:match ('%f[%a][Ee]dition$') then -- Ed, ed, Ed., ed., Edn, edn, Edn., edn. utilities.set_message ('err_extra_text_edition'); -- add error message end Edition = " " .. wrap_msg ('edition', Edition); else Edition = ''; end Series = utilities.is_set (Series) and wrap_msg ('series', {sepc, Series}) or ""; -- not the same as SeriesNum local Agency = A['Agency']; Agency = utilities.is_set (Agency) and wrap_msg ('agency', {sepc, Agency}) or ""; Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase); if utilities.is_set (AccessDate) then local retrv_text = " " .. cfg.messages['retrieved'] AccessDate = nowrap_date (AccessDate); -- wrap in nowrap span if date in appropriate format if (sepc ~= ".") then retrv_text = retrv_text:lower() end -- if mode is cs2, lower case AccessDate = utilities.substitute (retrv_text, AccessDate); -- add retrieved text AccessDate = utilities.substitute (cfg.presentation['accessdate'], {sepc, AccessDate}); -- allow editors to hide accessdates end if utilities.is_set (ID) then ID = sepc .. " " .. ID; end local Docket = A['Docket']; if "thesis" == config.CitationClass and utilities.is_set (Docket) then ID = sepc .. " Docket " .. Docket .. ID; end if "report" == config.CitationClass and utilities.is_set (Docket) then -- for cite report when |docket= is set ID = sepc .. ' ' .. Docket; -- overwrite ID even if |id= is set end if utilities.is_set (URL) then URL = " " .. external_link( URL, nil, URL_origin, UrlAccess ); end local Quote = A['Quote']; local TransQuote = A['TransQuote']; local ScriptQuote = A['ScriptQuote']; if utilities.is_set (Quote) or utilities.is_set (TransQuote) or utilities.is_set (ScriptQuote) then if utilities.is_set (Quote) then if Quote:sub(1, 1) == '"' and Quote:sub(-1, -1) == '"' then -- if first and last characters of quote are quote marks Quote = Quote:sub(2, -2); -- strip them off end end Quote = utilities.wrap_style ('quoted-text', Quote ); -- wrap in <q>...</q> tags if utilities.is_set (ScriptQuote) then Quote = script_concatenate (Quote, ScriptQuote, 'script-quote'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after quote is wrapped end if utilities.is_set (TransQuote) then if TransQuote:sub(1, 1) == '"' and TransQuote:sub(-1, -1) == '"' then -- if first and last characters of |trans-quote are quote marks TransQuote = TransQuote:sub(2, -2); -- strip them off end Quote = Quote .. " " .. utilities.wrap_style ('trans-quoted-title', TransQuote ); end if utilities.is_set (QuotePage) or utilities.is_set (QuotePages) then -- add page prefix local quote_prefix = ''; if utilities.is_set (QuotePage) then extra_text_in_page_check (QuotePage, 'quote-page'); -- add to maint cat if |quote-page= value begins with what looks like p., pp., etc. if not NoPP then quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, QuotePage}), '', '', ''; else quote_prefix = utilities.substitute (cfg.messages['nopp'], {sepc, QuotePage}), '', '', ''; end elseif utilities.is_set (QuotePages) then extra_text_in_page_check (QuotePages, 'quote-pages'); -- add to maint cat if |quote-pages= value begins with what looks like p., pp., etc. if tonumber(QuotePages) ~= nil and not NoPP then -- if only digits, assume single page quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, QuotePages}), '', ''; elseif not NoPP then quote_prefix = utilities.substitute (cfg.messages['pp-prefix'], {sepc, QuotePages}), '', ''; else quote_prefix = utilities.substitute (cfg.messages['nopp'], {sepc, QuotePages}), '', ''; end end Quote = quote_prefix .. ": " .. Quote; else Quote = sepc .. " " .. Quote; end PostScript = ""; -- cs1|2 does not supply terminal punctuation when |quote= is set end -- We check length of PostScript here because it will have been nuked by -- the quote parameters. We'd otherwise emit a message even if there wasn't -- a displayed postscript. -- TODO: Should the max size (1) be configurable? -- TODO: Should we check a specific pattern? if utilities.is_set(PostScript) and mw.ustring.len(PostScript) > 1 then utilities.set_message ('maint_postscript') end local Archived; if utilities.is_set (ArchiveURL) then local arch_text; if not utilities.is_set (ArchiveDate) then utilities.set_message ('err_archive_missing_date'); ArchiveDate = ''; -- empty string for concatenation end if "live" == UrlStatus then arch_text = cfg.messages['archived']; if sepc ~= "." then arch_text = arch_text:lower() end if utilities.is_set (ArchiveDate) then Archived = sepc .. ' ' .. utilities.substitute ( cfg.messages['archived-live'], {external_link( ArchiveURL, arch_text, A:ORIGIN('ArchiveURL'), nil) .. ArchiveFormat, ArchiveDate } ); else Archived = ''; end if not utilities.is_set (OriginalURL) then utilities.set_message ('err_archive_missing_url'); Archived = ''; -- empty string for concatenation end elseif utilities.is_set (OriginalURL) then -- UrlStatus is empty, 'dead', 'unfit', 'usurped', 'bot: unknown' if utilities.in_array (UrlStatus, {'unfit', 'usurped', 'bot: unknown'}) then arch_text = cfg.messages['archived-unfit']; if sepc ~= "." then arch_text = arch_text:lower() end Archived = sepc .. ' ' .. arch_text .. ArchiveDate; -- format already styled if 'bot: unknown' == UrlStatus then utilities.set_message ('maint_bot_unknown'); -- and add a category if not already added else utilities.set_message ('maint_unfit'); -- and add a category if not already added end else -- UrlStatus is empty, 'dead' arch_text = cfg.messages['archived-dead']; if sepc ~= "." then arch_text = arch_text:lower() end if utilities.is_set (ArchiveDate) then Archived = sepc .. " " .. utilities.substitute ( arch_text, { external_link( OriginalURL, cfg.messages['original'], OriginalURL_origin, OriginalAccess ) .. OriginalFormat, ArchiveDate } ); -- format already styled else Archived = ''; -- unset for concatenation end end else -- OriginalUrl not set arch_text = cfg.messages['archived-missing']; if sepc ~= "." then arch_text = arch_text:lower() end utilities.set_message ('err_archive_missing_url'); Archived = ''; -- empty string for concatenation end elseif utilities.is_set (ArchiveFormat) then Archived = ArchiveFormat; -- if set and ArchiveURL not set ArchiveFormat has error message else Archived = ''; end local Lay = ''; local LaySource = A['LaySource']; local LayURL = A['LayURL']; local LayFormat = A['LayFormat']; LayFormat = style_format (LayFormat, LayURL, 'lay-format', 'lay-url'); if utilities.is_set (LayURL) then if utilities.is_set (LayDate) then LayDate = " (" .. LayDate .. ")" end if utilities.is_set (LaySource) then LaySource = " &ndash; ''" .. utilities.safe_for_italics (LaySource) .. "''"; else LaySource = ""; end if sepc == '.' then Lay = sepc .. " " .. external_link( LayURL, cfg.messages['lay summary'], A:ORIGIN('LayURL'), nil ) .. LayFormat .. LaySource .. LayDate else Lay = sepc .. " " .. external_link( LayURL, cfg.messages['lay summary']:lower(), A:ORIGIN('LayURL'), nil ) .. LayFormat .. LaySource .. LayDate end elseif utilities.is_set (LayFormat) then -- Test if |lay-format= is given without giving a |lay-url= Lay = sepc .. LayFormat; -- if set and LayURL not set, then LayFormat has error message end local TranscriptURL = A['TranscriptURL'] local TranscriptFormat = A['TranscriptFormat']; TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, 'transcript-format', 'transcripturl'); local Transcript = A['Transcript']; local TranscriptURL_origin = A:ORIGIN('TranscriptURL'); -- get name of parameter that holds TranscriptURL if utilities.is_set (Transcript) then if utilities.is_set (TranscriptURL) then Transcript = external_link( TranscriptURL, Transcript, TranscriptURL_origin, nil ); end Transcript = sepc .. ' ' .. Transcript .. TranscriptFormat; elseif utilities.is_set (TranscriptURL) then Transcript = external_link( TranscriptURL, nil, TranscriptURL_origin, nil ); end local Publisher; if utilities.is_set (PublicationDate) then PublicationDate = wrap_msg ('published', PublicationDate); end if utilities.is_set (PublisherName) then if utilities.is_set (PublicationPlace) then Publisher = sepc .. " " .. PublicationPlace .. ": " .. PublisherName .. PublicationDate; else Publisher = sepc .. " " .. PublisherName .. PublicationDate; end elseif utilities.is_set (PublicationPlace) then Publisher= sepc .. " " .. PublicationPlace .. PublicationDate; else Publisher = PublicationDate; end local TransPeriodical = A['TransPeriodical']; local TransPeriodical_origin = A:ORIGIN ('TransPeriodical'); -- Several of the above rely upon detecting this as nil, so do it last. if (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical)) then if utilities.is_set (Title) or utilities.is_set (TitleNote) then Periodical = sepc .. " " .. format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin); else Periodical = format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin); end end local Language = A['Language']; if utilities.is_set (Language) then Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc. else Language=''; -- language not specified so make sure this is an empty string; --[[ TODO: need to extract the wrap_msg from language_parameter so that we can solve parentheses bunching problem with Format/Language/TitleType ]] end --[[ Handle the oddity that is cite speech. This code overrides whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided). ]] if "speech" == config.CitationClass then -- cite speech only TitleNote = TitleType; -- move TitleType to TitleNote so that it renders ahead of |event= TitleType = ''; -- and unset if utilities.is_set (Periodical) then -- if Periodical, perhaps because of an included |website= or |journal= parameter if utilities.is_set (Conference) then -- and if |event= is set Conference = Conference .. sepc .. " "; -- then add appropriate punctuation to the end of the Conference variable before rendering end end end -- Piece all bits together at last. Here, all should be non-nil. -- We build things this way because it is more efficient in LUA -- not to keep reassigning to the same string variable over and over. local tcommon; local tcommon2; -- used for book cite when |contributor= is set if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then if utilities.is_set (Others) then Others = safe_join ({Others, sepc .. " "}, sepc) end -- add terminal punctuation & space; check for dup sepc; TODO why do we need to do this here? tcommon = safe_join( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Edition, Publisher, Agency, Volume}, sepc ); elseif utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (Periodical) then -- special cases for book cites if utilities.is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc. tcommon = safe_join( {Title, TitleNote}, sepc ); -- author and other stuff will come after this and before tcommon2 tcommon2 = safe_join( {Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); else tcommon = safe_join( {Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); end elseif 'map' == config.CitationClass then -- special cases for cite map if utilities.is_set (Chapter) then -- map in a book; TitleType is part of Chapter tcommon = safe_join( {Title, Format, Edition, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc ); elseif utilities.is_set (Periodical) then -- map in a periodical tcommon = safe_join( {Title, TitleType, Format, Periodical, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc ); else -- a sheet or stand-alone map tcommon = safe_join( {Title, TitleType, Format, Edition, Scale, Series, Language, Cartography, Others, Publisher}, sepc ); end elseif 'episode' == config.CitationClass then -- special case for cite episode tcommon = safe_join( {Title, TitleNote, TitleType, Series, Language, Edition, Publisher}, sepc ); else -- all other CS1 templates tcommon = safe_join( {Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); end if #ID_list > 0 then ID_list = safe_join( { sepc .. " ", table.concat( ID_list, sepc .. " " ), ID }, sepc ); else ID_list = ID; end local Via = A['Via']; Via = utilities.is_set (Via) and wrap_msg ('via', Via) or ''; local idcommon; if 'audio-visual' == config.CitationClass or 'episode' == config.CitationClass then -- special case for cite AV media & cite episode position transcript idcommon = safe_join( { ID_list, URL, Archived, Transcript, AccessDate, Via, Lay, Quote }, sepc ); else idcommon = safe_join( { ID_list, URL, Archived, AccessDate, Via, Lay, Quote }, sepc ); end local text; local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At; local OrigDate = A['OrigDate']; OrigDate = utilities.is_set (OrigDate) and wrap_msg ('origdate', OrigDate) or ''; if utilities.is_set (Date) then if utilities.is_set (Authors) or utilities.is_set (Editors) then -- date follows authors or editors when authors not set Date = " (" .. Date .. ")" .. OrigDate .. sepc .. " "; -- in parentheses else -- neither of authors and editors set if (string.sub(tcommon, -1, -1) == sepc) then -- if the last character of tcommon is sepc Date = " " .. Date .. OrigDate; -- Date does not begin with sepc else Date = sepc .. " " .. Date .. OrigDate; -- Date begins with sepc end end end if utilities.is_set (Authors) then if (not utilities.is_set (Date)) then -- when date is set it's in parentheses; no Authors termination Authors = terminate_name_list (Authors, sepc); -- when no date, terminate with 0 or 1 sepc and a space end if utilities.is_set (Editors) then local in_text = " "; local post_text = ""; if utilities.is_set (Chapter) and 0 == #c then in_text = in_text .. cfg.messages['in'] .. " " if (sepc ~= '.') then in_text = in_text:lower() -- lowercase for cs2 end end if EditorCount <= 1 then post_text = " (" .. cfg.messages['editor'] .. ")"; -- be consistent with no-author, no-date case else post_text = " (" .. cfg.messages['editors'] .. ")"; end Editors = terminate_name_list (in_text .. Editors .. post_text, sepc); -- terminate with 0 or 1 sepc and a space end if utilities.is_set (Contributors) then -- book cite and we're citing the intro, preface, etc. local by_text = sepc .. ' ' .. cfg.messages['by'] .. ' '; if (sepc ~= '.') then by_text = by_text:lower() end -- lowercase for cs2 Authors = by_text .. Authors; -- author follows title so tweak it here if utilities.is_set (Editors) and utilities.is_set (Date) then -- when Editors make sure that Authors gets terminated Authors = terminate_name_list (Authors, sepc); -- terminate with 0 or 1 sepc and a space end if (not utilities.is_set (Date)) then -- when date is set it's in parentheses; no Contributors termination Contributors = terminate_name_list (Contributors, sepc); -- terminate with 0 or 1 sepc and a space end text = safe_join( {Contributors, Date, Chapter, tcommon, Authors, Place, Editors, tcommon2, pgtext, idcommon }, sepc ); else text = safe_join( {Authors, Date, Chapter, Place, Editors, tcommon, pgtext, idcommon }, sepc ); end elseif utilities.is_set (Editors) then if utilities.is_set (Date) then if EditorCount <= 1 then Editors = Editors .. ", " .. cfg.messages['editor']; else Editors = Editors .. ", " .. cfg.messages['editors']; end else if EditorCount <= 1 then Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " " else Editors = Editors .. " (" .. cfg.messages['editors'] .. ")" .. sepc .. " " end end text = safe_join( {Editors, Date, Chapter, Place, tcommon, pgtext, idcommon}, sepc ); else if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then text = safe_join( {Chapter, Place, tcommon, pgtext, Date, idcommon}, sepc ); else text = safe_join( {Chapter, Place, tcommon, Date, pgtext, idcommon}, sepc ); end end if utilities.is_set (PostScript) and PostScript ~= sepc then text = safe_join( {text, sepc}, sepc ); -- Deals with italics, spaces, etc. text = text:sub(1, -sepc:len() - 1); end text = safe_join( {text, PostScript}, sepc ); -- Now enclose the whole thing in a <cite> element local options_t = {}; options_t.class = cite_class_attribute_make (config.CitationClass, Mode); local Ref = is_valid_parameter_value (A['Ref'], A:ORIGIN('Ref'), cfg.keywords_lists['ref'], nil, true); -- nil when |ref=harv; A['Ref'] else if 'none' ~= cfg.keywords_xlate[(Ref and Ref:lower()) or ''] then local namelist_t = {}; -- holds selected contributor, author, editor name list local year = first_set ({Year, anchor_year}, 2); -- Year first for legacy citations and for YMD dates that require disambiguation if #c > 0 then -- if there is a contributor list namelist_t = c; -- select it elseif #a > 0 then -- or an author list namelist_t = a; elseif #e > 0 then -- or an editor list namelist_t = e; end local citeref_id; if #namelist_t > 0 then -- if there are names in namelist_t citeref_id = make_citeref_id (namelist_t, year); -- go make the CITEREF anchor if mw.uri.anchorEncode (citeref_id) == ((Ref and mw.uri.anchorEncode (Ref)) or '') then -- Ref may already be encoded (by {{sfnref}}) so citeref_id must be encoded before comparison utilities.set_message ('maint_ref_duplicates_default'); end else citeref_id = ''; -- unset end options_t.id = Ref or citeref_id; end if string.len (text:gsub('%b<>', '')) <= 2 then -- remove html and html-like tags; then get length of what remains; z.error_cats_t = {}; -- blank the categories list z.error_msgs_t = {}; -- blank the error messages list OCinSoutput = nil; -- blank the metadata string text = ''; -- blank the the citation utilities.set_message ('err_empty_citation'); -- set empty citation message and category end local render_t = {}; -- here we collect the final bits for concatenation into the rendered citation if utilities.is_set (options_t.id) then -- here we wrap the rendered citation in <cite ...>...</cite> tags table.insert (render_t, utilities.substitute (cfg.presentation['cite-id'], {mw.uri.anchorEncode(options_t.id), mw.text.nowiki(options_t.class), text})); -- when |ref= is set or when there is a namelist else table.insert (render_t, utilities.substitute (cfg.presentation['cite'], {mw.text.nowiki(options_t.class), text})); -- when |ref=none or when namelist_t empty and |ref= is missing or is empty end if OCinSoutput then -- blanked when citation is 'empty' so don't bother to add boilerplate metadata span table.insert (render_t, utilities.substitute (cfg.presentation['ocins'], OCinSoutput)); -- format and append metadata to the citation end local template_name = ('citation' == config.CitationClass) and 'citation' or 'cite ' .. (cfg.citation_class_map_t[config.CitationClass] or config.CitationClass); local template_link = '[[Template:' .. template_name .. '|' .. template_name .. ']]'; local msg_prefix = '<code class="cs1-code">{{' .. template_link .. '}}</code>: '; if 0 ~= #z.error_msgs_t then mw.addWarning (utilities.substitute (cfg.messages.warning_msg_e, template_link)); table.insert (render_t, ' '); -- insert a space between citation and its error messages table.sort (z.error_msgs_t); -- sort the error messages list; sorting includes wrapping <span> and <code> tags; hidden-error sorts ahead of visible-error local hidden = true; -- presume that the only error messages emited by this template are hidden for _, v in ipairs (z.error_msgs_t) do -- spin through the list of error messages if v:find ('cs1-visible-error', 1, true) then -- look for the visible error class name hidden = false; -- found one; so don't hide the error message prefix break; -- and done because no need to look further end end z.error_msgs_t[1] = table.concat ({utilities.error_comment (msg_prefix, hidden), z.error_msgs_t[1]}); -- add error message prefix to first error message to prevent extraneous punctuation table.insert (render_t, table.concat (z.error_msgs_t, '; ')); -- make a big string of error messages and add it to the rendering end if 0 ~= #z.maint_cats_t then mw.addWarning (utilities.substitute (cfg.messages.warning_msg_m, template_link)); table.sort (z.maint_cats_t); -- sort the maintenance messages list local maint_msgs_t = {}; -- here we collect all of the maint messages if 0 == #z.error_msgs_t then -- if no error messages table.insert (maint_msgs_t, msg_prefix); -- insert message prefix in maint message livery end for _, v in ipairs( z.maint_cats_t ) do -- append maintenance categories table.insert (maint_msgs_t, -- assemble new maint message and add it to the maint_msgs_t table table.concat ({v, ' (', utilities.substitute (cfg.messages[':cat wikilink'], v), ')'}) ); end table.insert (render_t, utilities.substitute (cfg.presentation['hidden-maint'], table.concat (maint_msgs_t, ' '))); -- wrap the group of maint messages with proper presentation and save end if not no_tracking_cats then for _, v in ipairs (z.error_cats_t) do -- append error categories table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v)); end for _, v in ipairs (z.maint_cats_t) do -- append maintenance categories table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v)); end for _, v in ipairs (z.prop_cats_t) do -- append properties categories table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v)); end end return table.concat (render_t); -- make a big string and done end --[[--------------------------< V A L I D A T E >-------------------------------------------------------------- Looks for a parameter's name in one of several whitelists. Parameters in the whitelist can have three values: true - active, supported parameters false - deprecated, supported parameters nil - unsupported parameters ]] local function validate (name, cite_class, empty) local name = tostring (name); local enum_name; -- for enumerated parameters, is name with enumerator replaced with '#' local state; local function state_test (state, name) -- local function to do testing of state values if true == state then return true; end -- valid actively supported parameter if false == state then if empty then return nil; end -- empty deprecated parameters are treated as unknowns deprecated_parameter (name); -- parameter is deprecated but still supported return true; end if 'tracked' == state then local base_name = name:gsub ('%d', ''); -- strip enumerators from parameter names that have them to get the base name utilities.add_prop_cat ('tracked-param', {base_name}, base_name); -- add a properties category; <base_name> modifies <key> return true; end return nil; end if name:find ('#') then -- # is a cs1|2 reserved character so parameters with # not permitted return nil; end if utilities.in_array (cite_class, whitelist.preprint_template_list ) then -- limited parameter sets allowed for these templates state = whitelist.limited_basic_arguments[name]; if true == state_test (state, name) then return true; end state = whitelist.preprint_arguments[cite_class][name]; -- look in the parameter-list for the template identified by cite_class if true == state_test (state, name) then return true; end -- limited enumerated parameters list enum_name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) state = whitelist.limited_numbered_arguments[enum_name]; if true == state_test (state, name) then return true; end return false; -- not supported because not found or name is set to nil end -- end limited parameter-set templates if utilities.in_array (cite_class, whitelist.unique_param_template_list) then -- experiment for template-specific parameters for templates that accept parameters from the basic argument list state = whitelist.unique_arguments[cite_class][name]; -- look in the template-specific parameter-lists for the template identified by cite_class if true == state_test (state, name) then return true; end end -- if here, fall into general validation state = whitelist.basic_arguments[name]; -- all other templates; all normal parameters allowed if true == state_test (state, name) then return true; end -- all enumerated parameters allowed enum_name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) state = whitelist.numbered_arguments[enum_name]; if true == state_test (state, name) then return true; end return false; -- not supported because not found or name is set to nil end --[=[-------------------------< I N T E R _ W I K I _ C H E C K >---------------------------------------------- check <value> for inter-language interwiki-link markup. <prefix> must be a MediaWiki-recognized language code. when these values have the form (without leading colon): [[<prefix>:link|label]] return label as plain-text [[<prefix>:link]] return <prefix>:link as plain-text return value as is else ]=] local function inter_wiki_check (parameter, value) local prefix = value:match ('%[%[(%a+):'); -- get an interwiki prefix if one exists local _; if prefix and cfg.inter_wiki_map[prefix:lower()] then -- if prefix is in the map, needs preceding colon so utilities.set_message ('err_bad_paramlink', parameter); -- emit an error message _, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink end return value; end --[[--------------------------< M I S S I N G _ P I P E _ C H E C K >------------------------------------------ Look at the contents of a parameter. If the content has a string of characters and digits followed by an equal sign, compare the alphanumeric string to the list of cs1|2 parameters. If found, then the string is possibly a parameter that is missing its pipe. There are two tests made: {{cite ... |title=Title access-date=2016-03-17}} -- the first parameter has a value and whitespace separates that value from the missing pipe parameter name {{cite ... |title=access-date=2016-03-17}} -- the first parameter has no value (whitespace after the first = is trimmed by MediaWiki) cs1|2 shares some parameter names with XML/HTML attributes: class=, title=, etc. To prevent false positives XML/HTML tags are removed before the search. If a missing pipe is detected, this function adds the missing pipe maintenance category. ]] local function missing_pipe_check (parameter, value) local capture; value = value:gsub ('%b<>', ''); -- remove XML/HTML tags because attributes: class=, title=, etc. capture = value:match ('%s+(%a[%w%-]+)%s*=') or value:match ('^(%a[%w%-]+)%s*='); -- find and categorize parameters with possible missing pipes if capture and validate (capture) then -- if the capture is a valid parameter name utilities.set_message ('err_missing_pipe', parameter); end end --[[--------------------------< H A S _ E X T R A N E O U S _ P U N C T >-------------------------------------- look for extraneous terminal punctuation in most parameter values; parameters listed in skip table are not checked ]] local function has_extraneous_punc (param, value) if 'number' == type (param) then return; end param = param:gsub ('%d+', '#'); -- enumerated name-list mask params allow terminal punct; normalize if cfg.punct_skip[param] then return; -- parameter name found in the skip table so done end if value:match ('[,;:]$') then utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat end if value:match ('^=') then -- sometimes an extraneous '=' character appears ... utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat end end --[[--------------------------< H A S _ E X T R A N E O U S _ U R L >------------------------------------------ look for extraneous url parameter values; parameters listed in skip table are not checked ]] local function has_extraneous_url (url_param_t) local url_error_t = {}; check_for_url (url_param_t, url_error_t); -- extraneous url check if 0 ~= #url_error_t then -- non-zero when there are errors table.sort (url_error_t); utilities.set_message ('err_param_has_ext_link', {utilities.make_sep_list (#url_error_t, url_error_t)}); -- add this error message end end --[[--------------------------< C I T A T I O N >-------------------------------------------------------------- This is used by templates such as {{cite book}} to create the actual citation text. ]] local function citation(frame) Frame = frame; -- save a copy in case we need to display an error message in preview mode local sandbox = '/sandbox' -- i18n: replace this rvalue with the name that your wiki uses to identify sandbox subpages is_sandbox = nil ~= string.find (frame:getTitle(), sandbox, 1, true); -- is this invoke the sandbox module? sandbox = is_sandbox and sandbox or ''; -- use i18n sandbox to load sandbox modules when this module is the sandox; live modules else local pframe = frame:getParent() local styles; cfg = mw.loadData ('Module:Citation/CS1/Configuration' .. sandbox); -- load sandbox versions of support modules when {{#invoke:Citation/CS1/sandbox|...}}; live modules else whitelist = mw.loadData ('Module:Citation/CS1/Whitelist' .. sandbox); utilities = require ('Module:Citation/CS1/Utilities' .. sandbox); validation = require ('Module:Citation/CS1/Date_validation' .. sandbox); identifiers = require ('Module:Citation/CS1/Identifiers' .. sandbox); metadata = require ('Module:Citation/CS1/COinS' .. sandbox); styles = 'Module:Citation/CS1' .. sandbox .. '/styles.css'; utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the selected cfg tables identifiers.set_selected_modules (cfg, utilities); -- so that functions in Identifiers can see the selected cfg tables and selected Utilities module validation.set_selected_modules (cfg, utilities); -- so that functions in Date validataion can see selected cfg tables and the selected Utilities module metadata.set_selected_modules (cfg, utilities); -- so that functions in COinS can see the selected cfg tables and selected Utilities module z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities is_preview_mode = not utilities.is_set (frame:preprocess ('{{REVISIONID}}')); local args = {}; -- table where we store all of the template's arguments local suggestions = {}; -- table where we store suggestions if we need to loadData them local error_text; -- used as a flag local config = {}; -- table to store parameters from the module {{#invoke:}} for k, v in pairs( frame.args ) do -- get parameters from the {{#invoke}} frame config[k] = v; -- args[k] = v; -- crude debug support that allows us to render a citation from module {{#invoke:}}; skips parameter validation; TODO: keep? end local capture; -- the single supported capture when matching unknown parameters using patterns local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing for k, v in pairs( pframe.args ) do -- get parameters from the parent (template) frame v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string if v ~= '' then if ('string' == type (k)) then k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- for enumerated parameters, translate 'local' digits to Western 0-9 end if not validate( k, config.CitationClass ) then if type (k) ~= 'string' then -- exclude empty numbered parameters if v:match("%S+") ~= nil then error_text = utilities.set_message ('err_text_ignored', {v}); end elseif validate (k:lower(), config.CitationClass) then error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, k:lower()}); -- suggest the lowercase version of the parameter else if nil == suggestions.suggestions then -- if this table is nil then we need to load it if is_sandbox then -- did the {{#invoke:}} use sandbox version? suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions/sandbox' ); -- use the sandbox version else suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions' ); -- use the live version end end for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter capture = k:match (pattern); -- the whole match if no capture in pattern else the capture if a match if capture then -- if the pattern matches param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator) if validate (param, config.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists) error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, param}); -- set the suggestion error message else error_text = utilities.set_message ('err_parameter_ignored', {k}); -- suggested param not supported by this template v = ''; -- unset end end end if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion? if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config.CitationClass) then utilities.set_message ('err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}); else utilities.set_message ('err_parameter_ignored', {k}); v = ''; -- unset value assigned to unrecognized parameters (this for the limited parameter lists) end end end end args[k] = v; -- save this parameter and its value elseif not utilities.is_set (v) then -- for empty parameters if not validate (k, config.CitationClass, true) then -- is this empty parameter a valid parameter k = ('' == k) and '(empty string)' or k; -- when k is empty string (or was space(s) trimmed to empty string), replace with descriptive text table.insert (empty_unknowns, utilities.wrap_style ('parameter', k)); -- format for error message and add to the list end -- crude debug support that allows us to render a citation from module {{#invoke:}} TODO: keep? -- elseif args[k] ~= nil or (k == 'postscript') then -- when args[k] has a value from {{#invoke}} frame (we don't normally do that) -- args[k] = v; -- overwrite args[k] with empty string from pframe.args[k] (template frame); v is empty string here end -- not sure about the postscript bit; that gets handled in parameter validation; historical artifact? end if 0 ~= #empty_unknowns then -- create empty unknown error message utilities.set_message ('err_param_unknown_empty', { 1 == #empty_unknowns and '' or 's', utilities.make_sep_list (#empty_unknowns, empty_unknowns) }); end local url_param_t = {}; for k, v in pairs( args ) do if 'string' == type (k) then -- don't evaluate positional parameters has_invisible_chars (k, v); -- look for invisible characters end has_extraneous_punc (k, v); -- look for extraneous terminal punctuation in parameter values missing_pipe_check (k, v); -- do we think that there is a parameter that is missing a pipe? args[k] = inter_wiki_check (k, v); -- when language interwiki-linked parameter missing leading colon replace with wiki-link label if 'string' == type (k) and not cfg.url_skip[k] then -- when parameter k is not positional and not in url skip table url_param_t[k] = v; -- make a parameter/value list for extraneous url check end end has_extraneous_url (url_param_t); -- look for url in parameter values where a url does not belong return table.concat ({ frame:extensionTag ('templatestyles', '', {src=styles}), citation0( config, args) }); end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return {citation = citation}; 5b914afd20bdaa8daab7192c9ee32f246e5bee9b Module:Citation/CS1/Configuration 828 51 118 117 2022-09-04T15:24:34Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local lang_obj = mw.language.getContentLanguage(); -- make a language object for the local language; used here for languages and dates --[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E S >------------------------------ List of namespaces that should not be included in citation error categories. Same as setting notracking = true by default. Note: Namespace names should use underscores instead of spaces. ]] local uncategorized_namespaces = { 'User', 'Talk', 'User_talk', 'Wikipedia_talk', 'File_talk', 'Template_talk', 'Help_talk', 'Category_talk', 'Portal_talk', 'Book_talk', 'Draft_talk', 'Education_Program_talk', 'Module_talk', 'MediaWiki_talk' }; local uncategorized_subpages = {'/[Ss]andbox', '/[Tt]estcases', '/[^/]*[Ll]og', '/[Aa]rchive'}; -- list of Lua patterns found in page names of pages we should not categorize --[[--------------------------< M E S S A G E S >-------------------------------------------------------------- Translation table The following contains fixed text that may be output as part of a citation. This is separated from the main body to aid in future translations of this module. ]] local messages = { ['agency'] = '$1 $2', -- $1 is sepc, $2 is agency ['archived-dead'] = 'Archived from $1 on $2', ['archived-live'] = '$1 from the original on $2', ['archived-missing'] = 'Archived from the original$1 on $2', ['archived-unfit'] = 'Archived from the original on ', ['archived'] = 'Archived', ['by'] = 'By', -- contributions to authored works: introduction, foreword, afterword ['cartography'] = 'Cartography by $1', ['editor'] = 'ed.', ['editors'] = 'eds.', ['edition'] = '($1&nbsp;ed.)', ['episode'] = 'Episode $1', ['et al'] = 'et&nbsp;al.', ['in'] = 'In', -- edited works ['inactive'] = 'inactive', ['inset'] = '$1 inset', ['interview'] = 'Interviewed by $1', ['lay summary'] = 'Lay summary', ['mismatch'] = '<code class="cs1-code">&#124;$1=</code> / <code class="cs1-code">&#124;$2=</code> mismatch', -- $1 is year param name; $2 is date param name ['newsgroup'] = '[[Usenet newsgroup|Newsgroup]]:&nbsp;$1', ['notitle'] = 'No title', -- for |title=(()) and (in the future) |title=none ['original'] = 'the original', ['origdate'] = ' [$1]', ['published'] = ' (published $1)', ['retrieved'] = 'Retrieved $1', ['season'] = 'Season $1', ['section'] = '§&nbsp;$1', ['sections'] = '§§&nbsp;$1', ['series'] = '$1 $2', -- $1 is sepc, $2 is series ['seriesnum'] = 'Series $1', ['translated'] = 'Translated by $1', ['type'] = ' ($1)', -- for titletype ['written'] = 'Written at $1', ['vol'] = '$1 Vol.&nbsp;$2', -- $1 is sepc; bold journal style volume is in presentation{} ['vol-no'] = '$1 Vol.&nbsp;$2, no.&nbsp;$3', -- sepc, volume, issue (alternatively insert $1 after $2, but then we'd also have to change capitalization) ['issue'] = '$1 No.&nbsp;$2', -- $1 is sepc ['j-vol'] = '$1 $2', -- sepc, volume; bold journal volume is in presentation{} ['j-issue'] = ' ($1)', ['nopp'] = '$1 $2'; -- page(s) without prefix; $1 is sepc ['p-prefix'] = "$1 p.&nbsp;$2", -- $1 is sepc ['pp-prefix'] = "$1 pp.&nbsp;$2", -- $1 is sepc ['j-page(s)'] = ': $1', -- same for page and pages ['sheet'] = '$1 Sheet&nbsp;$2', -- $1 is sepc ['sheets'] = '$1 Sheets&nbsp;$2', -- $1 is sepc ['j-sheet'] = ': Sheet&nbsp;$1', ['j-sheets'] = ': Sheets&nbsp;$1', ['language'] = '(in $1)', ['via'] = " &ndash; via $1", ['event'] = 'Event occurs at', ['minutes'] = 'minutes in', -- Determines the location of the help page ['help page link'] = 'Help:CS1 errors', ['help page label'] = 'help', -- categories ['cat wikilink'] = '[[Category:$1]]', -- $1 is the category name [':cat wikilink'] = '[[:Category:$1|link]]', -- category name as maintenance message wikilink; $1 is the category name -- Internal errors (should only occur if configuration is bad) ['undefined_error'] = 'Called with an undefined error condition', ['unknown_ID_key'] = 'Unrecognized ID key: ', -- an ID key in id_handlers not found in ~/Identifiers func_map{} ['unknown_ID_access'] = 'Unrecognized ID access keyword: ', -- an ID access keyword in id_handlers not found in keywords_lists['id-access']{} ['unknown_argument_map'] = 'Argument map not defined for this variable', ['bare_url_no_origin'] = 'Bare URL found but origin indicator is nil or empty', ['warning_msg_e'] = '<span style="color:#d33">One or more <code style="color: inherit; background: inherit; border: none; padding: inherit;">&#123;{$1}}</code> templates have errors</span>; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).'; -- $1 is template link ['warning_msg_m'] = '<span style="color:#3a3">One or more <code style="color: inherit; background: inherit; border: none; padding: inherit;">&#123;{$1}}</code> templates have maintenance messages</span>; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).'; -- $1 is template link } --[[--------------------------< C I T A T I O N _ C L A S S _ M A P >------------------------------------------ this table maps the value assigned to |CitationClass= in the cs1|2 templates to the canonical template name when the value assigned to |CitationClass= is different from the canonical template name. |CitationClass= values are used as class attributes in the <cite> tag that encloses the citation so these names may not contain spaces while the canonical template name may. These names are used in warning_msg_e and warning_msg_m to create links to the template's documentation when an article is displayed in preivew mode. Most cs1|2 template |CitationClass= values at en.wiki match their canonical template names so are not listed here. ]] local citation_class_map_t = { -- TODO: if kept, these and all other config.CitationClass 'names' require some sort of i18n ['audio-visual'] = 'AV media', -- TODO: move to ~/Configuration ['AV-media-notes'] = 'AV media notes', ['encyclopaedia'] = 'encyclopedia', ['mailinglist'] = 'mailing list', ['pressrelease'] = 'press release' } --[=[-------------------------< E T _ A L _ P A T T E R N S >-------------------------------------------------- This table provides Lua patterns for the phrase "et al" and variants in name text (author, editor, etc.). The main module uses these to identify and emit the 'etal' message. ]=] local et_al_patterns = { "[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][%.;,\"']*$", -- variations on the 'et al' theme "[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][Ii][AaIi][Ee]?[%.;,\"']*$", -- variations on the 'et alia', 'et alii' and 'et aliae' themes (false positive 'et aliie' unlikely to match) "[;,]? *%f[%a]and [Oo]thers", -- an alternative to et al. "%[%[ *[Ee][Tt]%.? *[Aa][Ll]%.? *%]%]", -- a wikilinked form "%(%( *[Ee][Tt]%.? *[Aa][Ll]%.? *%)%)", -- a double-bracketed form (to counter partial removal of ((...)) syntax) "[%(%[] *[Ee][Tt]%.? *[Aa][Ll]%.? *[%)%]]", -- a bracketed form } --[[--------------------------< P R E S E N T A T I O N >------------------------ Fixed presentation markup. Originally part of citation_config.messages it has been moved into its own, more semantically correct place. ]] local presentation = { -- .citation-comment class is specified at Help:CS1_errors#Controlling_error_message_display ['hidden-error'] = '<span class="cs1-hidden-error citation-comment">$1</span>', ['visible-error'] = '<span class="cs1-visible-error citation-comment">$1</span>', ['hidden-maint'] = '<span class="cs1-maint citation-comment">$1</span>', ['accessdate'] = '<span class="reference-accessdate">$1$2</span>', -- to allow editors to hide accessdate using personal CSS ['bdi'] = '<bdi$1>$2</bdi>', -- bidirectional isolation used with |script-title= and the like ['cite'] = '<cite class="$1">$2</cite>'; -- for use when citation does not have a namelist and |ref= not set so no id="..." attribute ['cite-id'] = '<cite id="$1" class="$2">$3</cite>'; -- for use when when |ref= is set or when citation has a namelist ['format'] = ' <span class="cs1-format">($1)</span>', -- for |format=, |chapter-format=, etc. -- various access levels, for |access=, |doi-access=, |arxiv=, ... -- narrow no-break space &#8239; may work better than nowrap CSS. Or not? Browser support? ['ext-link-access-signal'] = '<span class="$1" title="$2">$3</span>', -- external link with appropriate lock icon ['free'] = {class='cs1-lock-free', title='Freely accessible'}, -- classes defined in Module:Citation/CS1/styles.css ['registration'] = {class='cs1-lock-registration', title='Free registration required'}, ['limited'] = {class='cs1-lock-limited', title='Free access subject to limited trial, subscription normally required'}, ['subscription'] = {class='cs1-lock-subscription', title='Paid subscription required'}, ['interwiki-icon'] = '<span class="$1" title="$2">$3</span>', ['class-wikisource'] = 'cs1-ws-icon', ['italic-title'] = "''$1''", ['kern-left'] = '<span class="cs1-kern-left"></span>$1', -- spacing to use when title contains leading single or double quote mark ['kern-right'] = '$1<span class="cs1-kern-right"></span>', -- spacing to use when title contains trailing single or double quote mark ['nowrap1'] = '<span class="nowrap">$1</span>', -- for nowrapping an item: <span ...>yyyy-mm-dd</span> ['nowrap2'] = '<span class="nowrap">$1</span> $2', -- for nowrapping portions of an item: <span ...>dd mmmm</span> yyyy (note white space) ['ocins'] = '<span title="$1" class="Z3988"></span>', ['parameter'] = '<code class="cs1-code">&#124;$1=</code>', ['ps_cs1'] = '.'; -- CS1 style postscript (terminal) character ['ps_cs2'] = ''; -- CS2 style postscript (terminal) character (empty string) ['quoted-text'] = '<q>$1</q>', -- for wrapping |quote= content ['quoted-title'] = '"$1"', ['sep_cs1'] = '.', -- CS1 element separator ['sep_cs2'] = ',', -- CS2 separator ['sep_nl'] = ';', -- CS1|2 style name-list separator between names is a semicolon ['sep_nl_and'] = ' and ', -- used as last nl sep when |name-list-style=and and list has 2 items ['sep_nl_end'] = '; and ', -- used as last nl sep when |name-list-style=and and list has 3+ names ['sep_name'] = ', ', -- CS1|2 style last/first separator is <comma><space> ['sep_nl_vanc'] = ',', -- Vancouver style name-list separator between authors is a comma ['sep_name_vanc'] = ' ', -- Vancouver style last/first separator is a space ['sep_list'] = ', ', -- used for |language= when list has 3+ items except for last sep which uses sep_list_end ['sep_list_pair'] = ' and ', -- used for |language= when list has 2 items ['sep_list_end'] = ', and ', -- used as last list sep for |language= when list has 3+ items ['trans-italic-title'] = "&#91;''$1''&#93;", ['trans-quoted-title'] = "&#91;$1&#93;", -- for |trans-title= and |trans-quote= ['vol-bold'] = '$1 <b>$2</b>', -- sepc, volume; for bold journal cites; for other cites ['vol'] in messages{} } --[[--------------------------< A L I A S E S >--------------------------------- Aliases table for commonly passed parameters. Parameter names on the right side in the assignments in this table must have been defined in the Whitelist before they will be recognized as valid parameter names ]] local aliases = { ['AccessDate'] = {'access-date', 'accessdate'}, -- Used by InternetArchiveBot ['Agency'] = 'agency', ['ArchiveDate'] = {'archive-date', 'archivedate'}, -- Used by InternetArchiveBot ['ArchiveFormat'] = 'archive-format', ['ArchiveURL'] = {'archive-url', 'archiveurl'}, -- Used by InternetArchiveBot ['ASINTLD'] = 'asin-tld', ['At'] = 'at', -- Used by InternetArchiveBot ['Authors'] = {'authors', 'people', 'credits'}, ['BookTitle'] = {'book-title', 'booktitle'}, ['Cartography'] = 'cartography', ['Chapter'] = {'chapter', 'contribution', 'entry', 'article', 'section'}, ['ChapterFormat'] = {'chapter-format', 'contribution-format', 'entry-format', 'article-format', 'section-format'}; ['ChapterURL'] = {'chapter-url', 'contribution-url', 'entry-url', 'article-url', 'section-url', 'chapterurl'}, -- Used by InternetArchiveBot ['ChapterUrlAccess'] = {'chapter-url-access', 'contribution-url-access', 'entry-url-access', 'article-url-access', 'section-url-access'}, -- Used by InternetArchiveBot ['Class'] = 'class', -- cite arxiv and arxiv identifier ['Collaboration'] = 'collaboration', ['Conference'] = {'conference', 'event'}, ['ConferenceFormat'] = 'conference-format', ['ConferenceURL'] = 'conference-url', -- Used by InternetArchiveBot ['Date'] = {'date', 'air-date', 'airdate'}, -- air-date and airdate for cite episode and cite serial only ['Degree'] = 'degree', ['DF'] = 'df', ['DisplayAuthors'] = {'display-authors', 'display-subjects'}, ['DisplayContributors'] = 'display-contributors', ['DisplayEditors'] = 'display-editors', ['DisplayInterviewers'] = 'display-interviewers', ['DisplayTranslators'] = 'display-translators', ['Docket'] = 'docket', ['DoiBroken'] = 'doi-broken-date', ['Edition'] = 'edition', ['Embargo'] = 'pmc-embargo-date', ['Encyclopedia'] = {'encyclopedia', 'encyclopaedia', 'dictionary'}, -- cite encyclopedia only ['Episode'] = 'episode', -- cite serial only TODO: make available to cite episode? ['Format'] = 'format', ['ID'] = {'id', 'ID'}, ['Inset'] = 'inset', ['Issue'] = {'issue', 'number'}, ['Language'] = {'language', 'lang'}, ['LayDate'] = 'lay-date', ['LayFormat'] = 'lay-format', ['LaySource'] = 'lay-source', ['LayURL'] = 'lay-url', ['MailingList'] = {'mailing-list', 'mailinglist'}, -- cite mailing list only ['Map'] = 'map', -- cite map only ['MapFormat'] = 'map-format', -- cite map only ['MapURL'] = {'map-url', 'mapurl'}, -- cite map only -- Used by InternetArchiveBot ['MapUrlAccess'] = 'map-url-access', -- cite map only -- Used by InternetArchiveBot ['Minutes'] = 'minutes', ['Mode'] = 'mode', ['NameListStyle'] = 'name-list-style', ['Network'] = 'network', ['Newsgroup'] = 'newsgroup', -- cite newsgroup only ['NoPP'] = {'no-pp', 'nopp'}, ['NoTracking'] = {'no-tracking', 'template-doc-demo'}, ['Number'] = 'number', -- this case only for cite techreport ['OrigDate'] = {'orig-date', 'orig-year', 'origyear'}, ['Others'] = 'others', ['Page'] = {'page', 'p'}, -- Used by InternetArchiveBot ['Pages'] = {'pages', 'pp'}, -- Used by InternetArchiveBot ['Periodical'] = {'journal', 'magazine', 'newspaper', 'periodical', 'website', 'work'}, ['Place'] = {'place', 'location'}, ['PostScript'] = 'postscript', ['PublicationDate'] = {'publication-date', 'publicationdate'}, ['PublicationPlace'] = {'publication-place', 'publicationplace'}, ['PublisherName'] = {'publisher', 'institution'}, ['Quote'] = {'quote', 'quotation'}, ['QuotePage'] = 'quote-page', ['QuotePages'] = 'quote-pages', ['Ref'] = 'ref', ['Scale'] = 'scale', ['ScriptChapter'] = {'script-chapter', 'script-contribution', 'script-entry', 'script-article', 'script-section'}, ['ScriptMap'] = 'script-map', ['ScriptPeriodical'] = {'script-journal', 'script-magazine', 'script-newspaper', 'script-periodical', 'script-website', 'script-work'}, ['ScriptQuote'] = 'script-quote', ['ScriptTitle'] = 'script-title', -- Used by InternetArchiveBot ['Season'] = 'season', ['Sections'] = 'sections', -- cite map only ['Series'] = {'series', 'version'}, ['SeriesLink'] = {'series-link', 'serieslink'}, ['SeriesNumber'] = {'series-number', 'series-no'}, ['Sheet'] = 'sheet', -- cite map only ['Sheets'] = 'sheets', -- cite map only ['Station'] = 'station', ['Time'] = 'time', ['TimeCaption'] = 'time-caption', ['Title'] = 'title', -- Used by InternetArchiveBot ['TitleLink'] = {'title-link', 'episode-link', 'episodelink'}, -- Used by InternetArchiveBot ['TitleNote'] = 'department', ['TitleType'] = {'type', 'medium'}, ['TransChapter'] = {'trans-article', 'trans-chapter', 'trans-contribution', 'trans-entry', 'trans-section'}, ['Transcript'] = 'transcript', ['TranscriptFormat'] = 'transcript-format', ['TranscriptURL'] = {'transcript-url', 'transcripturl'}, -- Used by InternetArchiveBot ['TransMap'] = 'trans-map', -- cite map only ['TransPeriodical'] = {'trans-journal', 'trans-magazine', 'trans-newspaper', 'trans-periodical', 'trans-website', 'trans-work'}, ['TransQuote'] = 'trans-quote', ['TransTitle'] = 'trans-title', -- Used by InternetArchiveBot ['URL'] = {'url', 'URL'}, -- Used by InternetArchiveBot ['UrlAccess'] = 'url-access', -- Used by InternetArchiveBot ['UrlStatus'] = 'url-status', -- Used by InternetArchiveBot ['Vauthors'] = 'vauthors', ['Veditors'] = 'veditors', ['Via'] = 'via', ['Volume'] = 'volume', ['Year'] = 'year', ['AuthorList-First'] = {"first#", "author-first#", "author#-first", "given#", "author-given#", "author#-given"}, ['AuthorList-Last'] = {"last#", "author-last#", "author#-last", "surname#", "author-surname#", "author#-surname", "author#", "subject#", 'host#'}, ['AuthorList-Link'] = {"author-link#", "author#-link", "subject-link#", "subject#-link", "authorlink#", "author#link"}, ['AuthorList-Mask'] = {"author-mask#", "author#-mask", "subject-mask#", "subject#-mask"}, ['ContributorList-First'] = {'contributor-first#', 'contributor#-first', 'contributor-given#', 'contributor#-given'}, ['ContributorList-Last'] = {'contributor-last#', 'contributor#-last', 'contributor-surname#', 'contributor#-surname', 'contributor#'}, ['ContributorList-Link'] = {'contributor-link#', 'contributor#-link'}, ['ContributorList-Mask'] = {'contributor-mask#', 'contributor#-mask'}, ['EditorList-First'] = {"editor-first#", "editor#-first", "editor-given#", "editor#-given"}, ['EditorList-Last'] = {"editor-last#", "editor#-last", "editor-surname#", "editor#-surname", "editor#"}, ['EditorList-Link'] = {"editor-link#", "editor#-link"}, ['EditorList-Mask'] = {"editor-mask#", "editor#-mask"}, ['InterviewerList-First'] = {'interviewer-first#', 'interviewer#-first', 'interviewer-given#', 'interviewer#-given'}, ['InterviewerList-Last'] = {'interviewer-last#', 'interviewer#-last', 'interviewer-surname#', 'interviewer#-surname', 'interviewer#'}, ['InterviewerList-Link'] = {'interviewer-link#', 'interviewer#-link'}, ['InterviewerList-Mask'] = {'interviewer-mask#', 'interviewer#-mask'}, ['TranslatorList-First'] = {'translator-first#', 'translator#-first', 'translator-given#', 'translator#-given'}, ['TranslatorList-Last'] = {'translator-last#', 'translator#-last', 'translator-surname#', 'translator#-surname', 'translator#'}, ['TranslatorList-Link'] = {'translator-link#', 'translator#-link'}, ['TranslatorList-Mask'] = {'translator-mask#', 'translator#-mask'}, } --[[--------------------------< P U N C T _ S K I P >--------------------------- builds a table of parameter names that the extraneous terminal punctuation check should not check. ]] local punct_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value 'BookTitle', 'Chapter', 'ScriptChapter', 'ScriptTitle', 'Title', 'TransChapter', 'Transcript', 'TransMap', 'TransTitle', -- title-holding parameters 'AuthorList-Mask', 'ContributorList-Mask', 'EditorList-Mask', 'InterviewerList-Mask', 'TranslatorList-Mask', -- name-list mask may have name separators 'PostScript', 'Quote', 'ScriptQuote', 'TransQuote', 'Ref', -- miscellaneous 'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'LayURL', 'MapURL', 'TranscriptURL', 'URL', -- URL-holding parameters } local url_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value 'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'ID', 'LayURL', 'MapURL', 'TranscriptURL', 'URL', -- parameters allowed to hold urls 'Page', 'Pages', 'At', 'QuotePage', 'QuotePages', -- insource locators allowed to hold urls } local function build_skip_table (skip_t, meta_params) for _, meta_param in ipairs (meta_params) do -- for each meta parameter key local params = aliases[meta_param]; -- get the parameter or the table of parameters associated with the meta parameter name if 'string' == type (params) then skip_t[params] = 1; -- just a single parameter else for _, param in ipairs (params) do -- get the parameter name skip_t[param] = 1; -- add the parameter name to the skip table local count; param, count = param:gsub ('#', ''); -- remove enumerator marker from enumerated parameters if 0 ~= count then -- if removed skip_t[param] = 1; -- add param name without enumerator marker end end end end return skip_t; end local punct_skip = {}; local url_skip = {}; --[[-----------< S P E C I A L C A S E T R A N S L A T I O N S >------------ This table is primarily here to support internationalization. Translations in this table are used, for example, when an error message, category name, etc., is extracted from the English alias key. There may be other cases where this translation table may be useful. ]] local is_Latn = 'A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143'; local special_case_translation = { ['AuthorList'] = 'authors list', -- used to assemble maintenance category names ['ContributorList'] = 'contributors list', -- translation of these names plus translation of the base mainenance category names in maint_cats{} table below ['EditorList'] = 'editors list', -- must match the names of the actual categories ['InterviewerList'] = 'interviewers list', -- this group or translations used by name_has_ed_markup() and name_has_mult_names() ['TranslatorList'] = 'translators list', -- Lua patterns to match pseudo-titles used by InternetArchiveBot and others as placeholder for unknown |title= value ['archived_copy'] = { -- used with CS1 maint: Archive[d] copy as title ['en'] = '^archived?%s+copy$', -- for English; translators: keep this because templates imported from en.wiki ['local'] = nil, -- translators: replace ['local'] = nil with lowercase translation only when bots or tools create generic titles in your language }, -- Lua patterns to match generic titles; usually created by bots or reference filling tools -- translators: replace ['local'] = nil with lowercase translation only when bots or tools create generic titles in your language -- generic titles and patterns in this table should be lowercase only -- leave ['local'] nil except when there is a matching generic title in your language -- boolean 'true' for plain-text searches; 'false' for pattern searches ['generic_titles'] = { ['accept'] = { }, ['reject'] = { {['en'] = {'^wayback%s+machine$', false}, ['local'] = nil}, {['en'] = {'are you a robot', true}, ['local'] = nil}, {['en'] = {'hugedomains.com', true}, ['local'] = nil}, {['en'] = {'^[%(%[{<]?no +title[>}%]%)]?$', false}, ['local'] = nil}, {['en'] = {'page not found', true}, ['local'] = nil}, {['en'] = {'subscribe to read', true}, ['local'] = nil}, {['en'] = {'^[%(%[{<]?unknown[>}%]%)]?$', false}, ['local'] = nil}, {['en'] = {'website is for sale', true}, ['local'] = nil}, {['en'] = {'^404', false}, ['local'] = nil}, {['en'] = {'internet archive wayback machine', true}, ['local'] = nil}, {['en'] = {'log into facebook', true}, ['local'] = nil}, {['en'] = {'login • instagram', true}, ['local'] = nil}, {['en'] = {'redirecting...', true}, ['local'] = nil}, {['en'] = {'usurped title', true}, ['local'] = nil}, -- added by a GreenC bot {['en'] = {'webcite query result', true}, ['local'] = nil}, {['en'] = {'wikiwix\'s cache', true}, ['local'] = nil}, } }, -- boolean 'true' for plain-text searches, search string must be lowercase only -- boolean 'false' for pattern searches -- leave ['local'] nil except when there is a matching generic name in your language ['generic_names'] = { ['accept'] = { {['en'] = {'%[%[[^|]*%(author%) *|[^%]]*%]%]', false}, ['local'] = nil}, }, ['reject'] = { {['en'] = {'about us', true}, ['local'] = nil}, {['en'] = {'%f[%a][Aa]dvisor%f[%A]', false}, ['local'] = nil}, {['en'] = {'%f[%a][Aa]uthor%f[%A]', false}, ['local'] = nil}, {['en'] = {'collaborator', true}, ['local'] = nil}, {['en'] = {'contributor', true}, ['local'] = nil}, {['en'] = {'contact us', true}, ['local'] = nil}, {['en'] = {'directory', true}, ['local'] = nil}, {['en'] = {'%f[%(%[][%(%[]%s*eds?%.?%s*[%)%]]?$', false}, ['local'] = nil}, {['en'] = {'[,%.%s]%f[e]eds?%.?$', false}, ['local'] = nil}, {['en'] = {'^eds?[%.,;]', false}, ['local'] = nil}, {['en'] = {'^[%(%[]%s*[Ee][Dd][Ss]?%.?%s*[%)%]]', false}, ['local'] = nil}, {['en'] = {'%f[%a][Ee]dited%f[%A]', false}, ['local'] = nil}, {['en'] = {'%f[%a][Ee]ditors?%f[%A]', false}, ['local'] = nil}, {['en'] = {'%f[%a]]Ee]mail%f[%A]', false}, ['local'] = nil}, {['en'] = {'facebook', true}, ['local'] = nil}, {['en'] = {'google', true}, ['local'] = nil}, {['en'] = {'home page', true}, ['local'] = nil}, {['en'] = {'instagram', true}, ['local'] = nil}, {['en'] = {'interviewer', true}, ['local'] = nil}, {['en'] = {'linkedIn', true}, ['local'] = nil}, {['en'] = {'^[Nn]ews$', false}, ['local'] = nil}, {['en'] = {'pinterest', true}, ['local'] = nil}, {['en'] = {'policy', true}, ['local'] = nil}, {['en'] = {'privacy', true}, ['local'] = nil}, {['en'] = {'translator', true}, ['local'] = nil}, {['en'] = {'tumblr', true}, ['local'] = nil}, {['en'] = {'twitter', true}, ['local'] = nil}, {['en'] = {'site name', true}, ['local'] = nil}, {['en'] = {'statement', true}, ['local'] = nil}, {['en'] = {'submitted', true}, ['local'] = nil}, {['en'] = {'super.?user', false}, ['local'] = nil}, {['en'] = {'%f['..is_Latn..'][Uu]ser%f[^'..is_Latn..']', false}, ['local'] = nil}, {['en'] = {'verfasser', true}, ['local'] = nil}, } } } --[[--------------------------< D A T E _ N A M E S >---------------------------------------------------------- This table of tables lists local language date names and fallback English date names. The code in Date_validation will look first in the local table for valid date names. If date names are not found in the local table, the code will look in the English table. Because citations can be copied to the local wiki from en.wiki, the English is required when the date-name translation function date_name_xlate() is used. In these tables, season numbering is defined by Extended Date/Time Format (EDTF) Specification (https://www.loc.gov/standards/datetime/) which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using numbers 21-41. CS1|2 only supports generic seasons. EDTF does support the distinction between north and south hemisphere seasons but CS1|2 has no way to make that distinction. 33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each) The standard does not address 'named' dates so, for the purposes of CS1|2, Easter and Christmas are defined here as 98 and 99, which should be out of the ISO 8601 (EDTF) range of uses for a while. local_date_names_from_mediawiki is a boolean. When set to: true – module will fetch local month names from MediaWiki for both date_names['local']['long'] and date_names['local']['short'] false – module will *not* fetch local month names from MediaWiki Caveat lector: There is no guarantee that MediaWiki will provide short month names. At your wiki you can test the results of the MediaWiki fetch in the debug console with this command (the result is alpha sorted): =mw.dumpObject (p.date_names['local']) While the module can fetch month names from MediaWiki, it cannot fetch the quarter, season, and named date names from MediaWiki. Those must be translated manually. ]] local local_date_names_from_mediawiki = true; -- when false, manual translation required for date_names['local']['long'] and date_names['local']['short'] -- when true, module fetches long and short month names from MediaWiki local date_names = { ['en'] = { -- English ['long'] = {['January'] = 1, ['February'] = 2, ['March'] = 3, ['April'] = 4, ['May'] = 5, ['June'] = 6, ['July'] = 7, ['August'] = 8, ['September'] = 9, ['October'] = 10, ['November'] = 11, ['December'] = 12}, ['short'] = {['Jan'] = 1, ['Feb'] = 2, ['Mar'] = 3, ['Apr'] = 4, ['May'] = 5, ['Jun'] = 6, ['Jul'] = 7, ['Aug'] = 8, ['Sep'] = 9, ['Oct'] = 10, ['Nov'] = 11, ['Dec'] = 12}, ['quarter'] = {['First Quarter'] = 33, ['Second Quarter'] = 34, ['Third Quarter'] = 35, ['Fourth Quarter'] = 36}, ['season'] = {['Winter'] = 24, ['Spring'] = 21, ['Summer'] = 22, ['Fall'] = 23, ['Autumn'] = 23}, ['named'] = {['Easter'] = 98, ['Christmas'] = 99}, }, -- when local_date_names_from_mediawiki = false ['local'] = { -- replace these English date names with the local language equivalents ['long'] = {['January'] = 1, ['February'] = 2, ['March'] = 3, ['April'] = 4, ['May'] = 5, ['June'] = 6, ['July'] = 7, ['August'] = 8, ['September'] = 9, ['October'] = 10, ['November'] = 11, ['December'] = 12}, ['short'] = {['Jan'] = 1, ['Feb'] = 2, ['Mar'] = 3, ['Apr'] = 4, ['May'] = 5, ['Jun'] = 6, ['Jul'] = 7, ['Aug'] = 8, ['Sep'] = 9, ['Oct'] = 10, ['Nov'] = 11, ['Dec'] = 12}, ['quarter'] = {['First Quarter'] = 33, ['Second Quarter'] = 34, ['Third Quarter'] = 35, ['Fourth Quarter'] = 36}, ['season'] = {['Winter'] = 24, ['Spring'] = 21, ['Summer'] = 22, ['Fall'] = 23, ['Autumn'] = 23}, ['named'] = {['Easter'] = 98, ['Christmas'] = 99}, }, ['inv_local_long'] = {}, -- used in date reformatting & translation; copy of date_names['local'].long where k/v are inverted: [1]='<local name>' etc. ['inv_local_short'] = {}, -- used in date reformatting & translation; copy of date_names['local'].short where k/v are inverted: [1]='<local name>' etc. ['inv_local_quarter'] = {}, -- used in date translation; copy of date_names['local'].quarter where k/v are inverted: [1]='<local name>' etc. ['inv_local_season'] = {}, -- used in date translation; copy of date_names['local'].season where k/v are inverted: [1]='<local name>' etc. ['inv_local_named'] = {}, -- used in date translation; copy of date_names['local'].named where k/v are inverted: [1]='<local name>' etc. ['local_digits'] = {['0'] = '0', ['1'] = '1', ['2'] = '2', ['3'] = '3', ['4'] = '4', ['5'] = '5', ['6'] = '6', ['7'] = '7', ['8'] = '8', ['9'] = '9'}, -- used to convert local language digits to Western 0-9 ['xlate_digits'] = {}, } if local_date_names_from_mediawiki then -- if fetching local month names from MediaWiki is enabled local long_t = {}; local short_t = {}; for i=1, 12 do -- loop 12x and local name = lang_obj:formatDate('F', '2022-' .. i .. '-1'); -- get long month name for each i long_t[name] = i; -- save it name = lang_obj:formatDate('M', '2022-' .. i .. '-1'); -- get short month name for each i short_t[name] = i; -- save it end date_names['local']['long'] = long_t; -- write the long table – overwrites manual translation date_names['local']['short'] = short_t; -- write the short table – overwrites manual translation end -- create inverted date-name tables for reformatting and/or translation for _, invert_t in pairs {{'long', 'inv_local_long'}, {'short', 'inv_local_short'}, {'quarter', 'inv_local_quarter'}, {'season', 'inv_local_season'}, {'named', 'inv_local_named'}} do for name, i in pairs (date_names['local'][invert_t[1]]) do -- this table is ['name'] = i date_names[invert_t[2]][i] = name; -- invert to get [i] = 'name' for conversions from ymd end end for ld, ed in pairs (date_names.local_digits) do -- make a digit translation table for simple date translation from en to local language using local_digits table date_names.xlate_digits [ed] = ld; -- en digit becomes index with local digit as the value end local df_template_patterns = { -- table of redirects to {{Use dmy dates}} and {{Use mdy dates}} '{{ *[Uu]se +(dmy) +dates *[|}]', -- 1159k -- sorted by approximate transclusion count '{{ *[Uu]se +(mdy) +dates *[|}]', -- 212k '{{ *[Uu]se +(MDY) +dates *[|}]', -- 788 '{{ *[Uu]se +(DMY) +dates *[|}]', -- 343 '{{ *([Mm]dy) *[|}]', -- 176 '{{ *[Uu]se *(dmy) *[|}]', -- 156 + 18 '{{ *[Uu]se *(mdy) *[|}]', -- 149 + 11 '{{ *([Dd]my) *[|}]', -- 56 '{{ *[Uu]se +(MDY) *[|}]', -- 5 '{{ *([Dd]MY) *[|}]', -- 3 '{{ *[Uu]se(mdy)dates *[|}]', -- 1 '{{ *[Uu]se +(DMY) *[|}]', -- 0 '{{ *([Mm]DY) *[|}]', -- 0 } local function get_date_format () local title_object = mw.title.getCurrentTitle(); if title_object.namespace == 10 then -- not in template space so that unused templates appear in unused-template-reports; return nil; -- auto-formatting does not work in Template space so don't set global_df end local content = title_object:getContent() or ''; -- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625 for _, pattern in ipairs (df_template_patterns) do -- loop through the patterns looking for {{Use dmy dates}} or {{Use mdy dates}} or any of their redirects local start, _, match = content:find(pattern); -- match is the three letters indicating desired date format if match then content = content:match ('%b{}', start); -- get the whole template if content:match ('| *cs1%-dates *= *[lsy][sy]?') then -- look for |cs1-dates=publication date length access-/archive-date length return match:lower() .. '-' .. content:match ('| *cs1%-dates *= *([lsy][sy]?)'); else return match:lower() .. '-all'; -- no |cs1-dates= k/v pair; return value appropriate for use in |df= end end end end local global_df; --[[-----------------< V O L U M E , I S S U E , P A G E S >------------------ These tables hold cite class values (from the template invocation) and identify those templates that support |volume=, |issue=, and |page(s)= parameters. Cite conference and cite map require further qualification which is handled in the main module. ]] local templates_using_volume = {'citation', 'audio-visual', 'book', 'conference', 'encyclopaedia', 'interview', 'journal', 'magazine', 'map', 'news', 'report', 'techreport', 'thesis'} local templates_using_issue = {'citation', 'conference', 'episode', 'interview', 'journal', 'magazine', 'map', 'news', 'podcast'} local templates_not_using_page = {'audio-visual', 'episode', 'mailinglist', 'newsgroup', 'podcast', 'serial', 'sign', 'speech'} --[[ These tables control when it is appropriate for {{citation}} to render |volume= and/or |issue=. The parameter names in the tables constrain {{citation}} so that its renderings match the renderings of the equivalent cs1 templates. For example, {{cite web}} does not support |volume= so the equivalent {{citation |website=...}} must not support |volume=. ]] local citation_no_volume_t = { -- {{citation}} does not render |volume= when these parameters are used 'website', 'mailinglist', 'script-website', } local citation_issue_t = { -- {{citation}} may render |issue= when these parameters are used 'journal', 'magazine', 'newspaper', 'periodical', 'work', 'script-journal', 'script-magazine', 'script-newspaper', 'script-periodical', 'script-work', } --[[ Patterns for finding extra text in |volume=, |issue=, |page=, |pages= ]] local vol_iss_pg_patterns = { good_ppattern = '^P[^%.PpGg]', -- OK to begin with uppercase P: P7 (page 7 of section P), but not p123 (page 123); TODO: this allows 'Pages' which it should not bad_ppatterns = { -- patterns for |page= and |pages= '^[Pp][PpGg]?%.?[ %d]', '^[Pp][Pp]?%.&nbsp;', -- from {{p.}} and {{pp.}} templates '^[Pp]ages?', '^[Pp]gs.?', }, vpatterns = { -- patterns for |volume= '^volumes?', '^vols?[%.:=]?' }, ipatterns = { -- patterns for |issue= '^issues?', '^iss[%.:=]?', '^numbers?', '^nos?%A', -- don't match 'november' or 'nostradamus' '^nr[%.:=]?', '^n[%.:= ]' -- might be a valid issue without separator (space char is sep char here) } } --[[--------------------------< K E Y W O R D S >------------------------------- These tables hold keywords for those parameters that have defined sets of acceptable keywords. ]] --[[-------------------< K E Y W O R D S T A B L E >-------------------------- this is a list of keywords; each key in the list is associated with a table of synonymous keywords possibly from different languages. for I18N: add local-language keywords to value table; do not change the key. For example, adding the German keyword 'ja': ['affirmative'] = {'yes', 'true', 'y', 'ja'}, Because CS1|2 templates from en.wiki articles are often copied to other local wikis, it is recommended that the English keywords remain in these tables. ]] local keywords = { ['amp'] = {'&', 'amp', 'ampersand'}, -- |name-list-style= ['and'] = {'and', 'serial'}, -- |name-list-style= ['affirmative'] = {'yes', 'true', 'y'}, -- |no-tracking=, |no-pp= -- Used by InternetArchiveBot ['afterword'] = {'afterword'}, -- |contribution= ['bot: unknown'] = {'bot: unknown'}, -- |url-status= -- Used by InternetArchiveBot ['cs1'] = {'cs1'}, -- |mode= ['cs2'] = {'cs2'}, -- |mode= ['dead'] = {'dead', 'deviated'}, -- |url-status= -- Used by InternetArchiveBot ['dmy'] = {'dmy'}, -- |df= ['dmy-all'] = {'dmy-all'}, -- |df= ['foreword'] = {'foreword'}, -- |contribution= ['free'] = {'free'}, -- |<id>-access= -- Used by InternetArchiveBot ['harv'] = {'harv'}, -- |ref=; this no longer supported; is_valid_parameter_value() called with <invert> = true ['introduction'] = {'introduction'}, -- |contribution= ['limited'] = {'limited'}, -- |url-access= -- Used by InternetArchiveBot ['live'] = {'live'}, -- |url-status= -- Used by InternetArchiveBot ['mdy'] = {'mdy'}, -- |df= ['mdy-all'] = {'mdy-all'}, -- |df= ['none'] = {'none'}, -- |postscript=, |ref=, |title=, |type= -- Used by InternetArchiveBot ['off'] = {'off'}, -- |title= (potentially also: |title-link=, |postscript=, |ref=, |type=) ['preface'] = {'preface'}, -- |contribution= ['registration'] = {'registration'}, -- |url-access= -- Used by InternetArchiveBot ['subscription'] = {'subscription'}, -- |url-access= -- Used by InternetArchiveBot ['unfit'] = {'unfit'}, -- |url-status= -- Used by InternetArchiveBot ['usurped'] = {'usurped'}, -- |url-status= -- Used by InternetArchiveBot ['vanc'] = {'vanc'}, -- |name-list-style= ['ymd'] = {'ymd'}, -- |df= ['ymd-all'] = {'ymd-all'}, -- |df= -- ['yMd'] = {'yMd'}, -- |df=; not supported at en.wiki -- ['yMd-all'] = {'yMd-all'}, -- |df=; not supported at en.wiki } --[[------------------------< X L A T E _ K E Y W O R D S >--------------------- this function builds a list, keywords_xlate{}, of the keywords found in keywords{} where the values from keywords{} become the keys in keywords_xlate{} and the keys from keywords{} become the values in keywords_xlate{}: ['affirmative'] = {'yes', 'true', 'y'}, -- in keywords{} becomes ['yes'] = 'affirmative', -- in keywords_xlate{} ['true'] = 'affirmative', ['y'] = 'affirmative', the purpose of this function is to act as a translator between a non-English keyword and its English equivalent that may be used in other modules of this suite ]] local function xlate_keywords () local out_table = {}; -- output goes here for k, keywords_t in pairs (keywords) do -- spin through the keywords table for _, keyword in ipairs (keywords_t) do -- for each keyword out_table[keyword] = k; -- create an entry in the output table where keyword is the key end end return out_table; end local keywords_xlate = xlate_keywords (); -- the list of translated keywords --[[----------------< M A K E _ K E Y W O R D S _ L I S T >--------------------- this function assembles, for parameter-value validation, the list of keywords appropriate to that parameter. keywords_lists{}, is a table of tables from keywords{} ]] local function make_keywords_list (keywords_lists) local out_table = {}; -- output goes here for _, keyword_list in ipairs (keywords_lists) do -- spin through keywords_lists{} and get a table of keywords for _, keyword in ipairs (keyword_list) do -- spin through keyword_list{} and add each keyword, ... table.insert (out_table, keyword); -- ... as plain text, to the output list end end return out_table; end --[[----------------< K E Y W O R D S _ L I S T S >----------------------------- this is a list of lists of valid keywords for the various parameters in [key]. Generally the keys in this table are the canonical en.wiki parameter names though some are contrived because of use in multiple differently named parameters: ['yes_true_y'], ['id-access']. The function make_keywords_list() extracts the individual keywords from the appropriate list in keywords{}. The lists in this table are used to validate the keyword assignment for the parameters named in this table's keys. ]] local keywords_lists = { ['yes_true_y'] = make_keywords_list ({keywords.affirmative}), ['contribution'] = make_keywords_list ({keywords.afterword, keywords.foreword, keywords.introduction, keywords.preface}), ['df'] = make_keywords_list ({keywords.dmy, keywords['dmy-all'], keywords.mdy, keywords['mdy-all'], keywords.ymd, keywords['ymd-all']}), -- ['df'] = make_keywords_list ({keywords.dmy, keywords['dmy-all'], keywords.mdy, keywords['mdy-all'], keywords.ymd, keywords['ymd-all'], keywords.yMd, keywords['yMd-all']}), -- not supported at en.wiki ['mode'] = make_keywords_list ({keywords.cs1, keywords.cs2}), ['name-list-style'] = make_keywords_list ({keywords.amp, keywords['and'], keywords.vanc}), ['ref'] = make_keywords_list ({keywords.harv}), -- inverted check; |ref=harv no longer supported ['url-access'] = make_keywords_list ({keywords.subscription, keywords.limited, keywords.registration}), ['url-status'] = make_keywords_list ({keywords.dead, keywords.live, keywords.unfit, keywords.usurped, keywords['bot: unknown']}), ['id-access'] = make_keywords_list ({keywords.free}), } --[[---------------------< S T R I P M A R K E R S >---------------------------- Common pattern definition location for stripmarkers so that we don't have to go hunting for them if (when) MediaWiki changes their form. ]] local stripmarkers = { ['any'] = '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', -- capture returns name of stripmarker ['math'] = '\127[^\127]*UNIQ%-%-math%-[%a%d]+%-QINU[^\127]*\127' -- math stripmarkers used in coins_cleanup() and coins_replace_math_stripmarker() } --[[------------< I N V I S I B L E _ C H A R A C T E R S >--------------------- This table holds non-printing or invisible characters indexed either by name or by Unicode group. Values are decimal representations of UTF-8 codes. The table is organized as a table of tables because the Lua pairs keyword returns table data in an arbitrary order. Here, we want to process the table from top to bottom because the entries at the top of the table are also found in the ranges specified by the entries at the bottom of the table. Also here is a pattern that recognizes stripmarkers that begin and end with the delete characters. The nowiki stripmarker is not an error but some others are because the parameter values that include them become part of the template's metadata before stripmarker replacement. ]] local invisible_defs = { del = '\127', -- used to distinguish between stripmarker and del char zwj = '\226\128\141', -- used with capture because zwj may be allowed } local invisible_chars = { {'replacement', '\239\191\189'}, -- U+FFFD, EF BF BD {'zero width joiner', '('.. invisible_defs.zwj .. ')'}, -- U+200D, E2 80 8D; capture because zwj may be allowed {'zero width space', '\226\128\139'}, -- U+200B, E2 80 8B {'hair space', '\226\128\138'}, -- U+200A, E2 80 8A {'soft hyphen', '\194\173'}, -- U+00AD, C2 AD {'horizontal tab', '\009'}, -- U+0009 (HT), 09 {'line feed', '\010'}, -- U+000A (LF), 0A {'no-break space', '\194\160'}, -- U+00A0 (NBSP), C2 A0 {'carriage return', '\013'}, -- U+000D (CR), 0D {'stripmarker', stripmarkers.any}, -- stripmarker; may or may not be an error; capture returns the stripmaker type {'delete', '('.. invisible_defs.del .. ')'}, -- U+007F (DEL), 7F; must be done after stripmarker test; capture to distinguish isolated del chars not part of stripmarker {'C0 control', '[\000-\008\011\012\014-\031]'}, -- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D)) {'C1 control', '[\194\128-\194\159]'}, -- U+0080–U+009F (XXX–APC), C2 80 – C2 9F -- {'Specials', '[\239\191\185-\239\191\191]'}, -- U+FFF9-U+FFFF, EF BF B9 – EF BF BF -- {'Private use area', '[\238\128\128-\239\163\191]'}, -- U+E000–U+F8FF, EE 80 80 – EF A3 BF -- {'Supplementary Private Use Area-A', '[\243\176\128\128-\243\191\191\189]'}, -- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD -- {'Supplementary Private Use Area-B', '[\244\128\128\128-\244\143\191\189]'}, -- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD } --[[ Indic script makes use of zero width joiner as a character modifier so zwj characters must be left in. This pattern covers all of the unicode characters for these languages: Devanagari 0900–097F – https://unicode.org/charts/PDF/U0900.pdf Devanagari extended A8E0–A8FF – https://unicode.org/charts/PDF/UA8E0.pdf Bengali 0980–09FF – https://unicode.org/charts/PDF/U0980.pdf Gurmukhi 0A00–0A7F – https://unicode.org/charts/PDF/U0A00.pdf Gujarati 0A80–0AFF – https://unicode.org/charts/PDF/U0A80.pdf Oriya 0B00–0B7F – https://unicode.org/charts/PDF/U0B00.pdf Tamil 0B80–0BFF – https://unicode.org/charts/PDF/U0B80.pdf Telugu 0C00–0C7F – https://unicode.org/charts/PDF/U0C00.pdf Kannada 0C80–0CFF – https://unicode.org/charts/PDF/U0C80.pdf Malayalam 0D00–0D7F – https://unicode.org/charts/PDF/U0D00.pdf plus the not-necessarily Indic scripts for Sinhala and Burmese: Sinhala 0D80-0DFF - https://unicode.org/charts/PDF/U0D80.pdf Myanmar 1000-109F - https://unicode.org/charts/PDF/U1000.pdf Myanmar extended A AA60-AA7F - https://unicode.org/charts/PDF/UAA60.pdf Myanmar extended B A9E0-A9FF - https://unicode.org/charts/PDF/UA9E0.pdf the pattern is used by has_invisible_chars() and coins_cleanup() ]] local indic_script = '[\224\164\128-\224\181\191\224\163\160-\224\183\191\225\128\128-\225\130\159\234\167\160-\234\167\191\234\169\160-\234\169\191]'; -- list of emoji that use zwj character (U+200D) to combine with another emoji local emoji = { -- indexes are decimal forms of the hex values in U+xxxx [127752] = true, -- U+1F308 🌈 rainbow [127806] = true, -- U+1F33E 🌾 ear of rice [127859] = true, -- U+1F373 🍳 cooking [127891] = true, -- U+1F393 🎓 graduation cap [127908] = true, -- U+1F3A4 🎤 microphone [127912] = true, -- U+1F3A8 🎨 artist palette [127979] = true, -- U+1F3EB 🏫 school [127981] = true, -- U+1F3ED 🏭 factory [128102] = true, -- U+1F466 👦 boy [128103] = true, -- U+1F467 👧 girl [128104] = true, -- U+1F468 👨 man [128105] = true, -- U+1F469 👩 woman [128139] = true, -- U+1F48B 💋 kiss mark [128187] = true, -- U+1F4BB 💻 personal computer [128188] = true, -- U+1F4BC 💼 brief case [128295] = true, -- U+1F527 🔧 wrench [128300] = true, -- U+1F52C 🔬 microscope [128488] = true, -- U+1F5E8 🗨 left speech bubble [128640] = true, -- U+1F680 🚀 rocket [128658] = true, -- U+1F692 🚒 fire engine [129309] = true, -- U+1F91D 🤝 handshake [129455] = true, -- U+1F9AF 🦯 probing cane [129456] = true, -- U+1F9B0 🦰 emoji component red hair [129457] = true, -- U+1F9B1 🦱 emoji component curly hair [129458] = true, -- U+1F9B2 🦲 emoji component bald [129459] = true, -- U+1F9B3 🦳 emoji component white hair [129466] = true, -- U+1F9BA 🦺 safety vest [129468] = true, -- U+1F9BC 🦼 motorized wheelchair [129469] = true, -- U+1F9BD 🦽 manual wheelchair [129489] = true, -- U+1F9D1 🧑 adult [9760] = true, -- U+2620 ☠ skull and crossbones [9792] = true, -- U+2640 ♀ female sign [9794] = true, -- U+2642 ♂ male sign [9877] = true, -- U+2695 ⚕ staff of aesculapius [9878] = true, -- U+2696 ⚖ scales [9992] = true, -- U+2708 ✈ airplane [10084] = true, -- U+2764 ❤ heavy black heart } --[[----------------------< L A N G U A G E S U P P O R T >------------------- These tables and constants support various language-specific functionality. ]] --local this_wiki_code = mw.getContentLanguage():getCode(); -- get this wiki's language code local this_wiki_code = lang_obj:getCode(); -- get this wiki's language code if string.match (mw.site.server, 'wikidata') then this_wiki_code = mw.getCurrentFrame():preprocess('{{int:lang}}'); -- on Wikidata so use interface language setting instead end local mw_languages_by_tag_t = mw.language.fetchLanguageNames (this_wiki_code, 'all'); -- get a table of language tag/name pairs known to Wikimedia; used for interwiki tests local mw_languages_by_name_t = {}; for k, v in pairs (mw_languages_by_tag_t) do -- build a 'reversed' table name/tag language pairs know to MediaWiki; used for |language= v = mw.ustring.lower (v); -- lowercase for tag fetch; get name's proper case from mw_languages_by_tag_t[<tag>] if mw_languages_by_name_t[v] then -- when name already in the table if 2 == #k or 3 == #k then -- if tag does not have subtags mw_languages_by_name_t[v] = k; -- prefer the shortest tag for this name end else -- here when name not in the table mw_languages_by_name_t[v] = k; -- so add name and matching tag end end local inter_wiki_map = {}; -- map of interwiki prefixes that are language-code prefixes for k, v in pairs (mw.site.interwikiMap ('local')) do -- spin through the base interwiki map (limited to local) if mw_languages_by_tag_t[v["prefix"]] then -- if the prefix matches a known language tag inter_wiki_map[v["prefix"]] = true; -- add it to our local map end end --[[--------------------< S C R I P T _ L A N G _ C O D E S >------------------- This table is used to hold ISO 639-1 two-character and ISO 639-3 three-character language codes that apply only to |script-title= and |script-chapter= ]] local script_lang_codes = { 'ab', 'am', 'ar', 'be', 'bg', 'bn', 'bo', 'bs', 'dv', 'dz', 'el', 'fa', 'gu', 'he', 'hi', 'hy', 'ja', 'ka', 'kk', 'km', 'kn', 'ko', 'ku', 'ky', 'lo', 'mk', 'ml', 'mn', 'mr', 'my', 'ne', 'or', 'ota', 'ps', 'ru', 'sd', 'si', 'sr', 'syc', 'ta', 'te', 'tg', 'th', 'ti', 'ug', 'uk', 'ur', 'uz', 'yi', 'yue', 'zh' }; --[[---------------< L A N G U A G E R E M A P P I N G >---------------------- These tables hold language information that is different (correct) from MediaWiki's definitions For each ['code'] = 'language name' in lang_code_remap{} there must be a matching ['language name'] = {'language name', 'code'} in lang_name_remap{} lang_code_remap{}: key is always lowercase ISO 639-1, -2, -3 language code or a valid lowercase IETF language tag value is properly spelled and capitalized language name associated with key only one language name per key; key/value pair must have matching entry in lang_name_remap{} lang_name_remap{}: key is always lowercase language name value is a table the holds correctly spelled and capitalized language name [1] and associated code [2] (code must match a code key in lang_code_remap{}) may have multiple keys referring to a common preferred name and code; For example: ['kolsch'] and ['kölsch'] both refer to 'Kölsch' and 'ksh' ]] local lang_code_remap = { -- used for |language= and |script-title= / |script-chapter= ['als'] = 'Tosk Albanian', -- MediaWiki returns Alemannisch ['bh'] = 'Bihari', -- MediaWiki uses 'bh' as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org ['bla'] = 'Blackfoot', -- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name ['bn'] = 'Bengali', -- MediaWiki returns Bangla ['ca-valencia'] = 'Valencian', -- IETF variant of Catalan ['ilo'] = 'Ilocano', -- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name ['ksh'] = 'Kölsch', -- MediaWiki: Colognian; use IANA/ISO 639 preferred name ['ksh-x-colog'] = 'Colognian', -- override MediaWiki ksh; no IANA/ISO 639 code for Colognian; IETF private code created at Module:Lang/data ['mis-x-ripuar'] = 'Ripuarian', -- override MediaWiki ksh; no IANA/ISO 639 code for Ripuarian; IETF private code created at Module:Lang/data ['nan-tw'] = 'Taiwanese Hokkien', -- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese and support en.wiki preferred name } local lang_name_remap = { -- used for |language=; names require proper capitalization; tags must be lowercase ['alemannisch'] = {'Swiss German', 'gsw'}, -- not an ISO or IANA language name; MediaWiki uses 'als' as a subdomain name for Alemannic Wikipedia: als.wikipedia.org ['bangla'] = {'Bengali', 'bn'}, -- MediaWiki returns Bangla (the endonym) but we want Bengali (the exonym); here we remap ['bengali'] = {'Bengali', 'bn'}, -- MediaWiki doesn't use exonym so here we provide correct language name and 639-1 code ['bhojpuri'] = {'Bhojpuri', 'bho'}, -- MediaWiki uses 'bh' as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org ['bihari'] = {'Bihari', 'bh'}, -- MediaWiki replaces 'Bihari' with 'Bhojpuri' so 'Bihari' cannot be found ['blackfoot'] = {'Blackfoot', 'bla'}, -- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name ['colognian'] = {'Colognian', 'ksh-x-colog'}, -- MediaWiki preferred name for ksh ['ilocano'] = {'Ilocano', 'ilo'}, -- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name ['kolsch'] = {'Kölsch', 'ksh'}, -- use IANA/ISO 639 preferred name (use non-diacritical o instead of umlaut ö) ['kölsch'] = {'Kölsch', 'ksh'}, -- use IANA/ISO 639 preferred name ['ripuarian'] = {'Ripuarian', 'mis-x-ripuar'}, -- group of dialects; no code in MediaWiki or in IANA/ISO 639 ['taiwanese hokkien'] = {'Taiwanese Hokkien', 'nan-tw'}, -- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese ['tosk albanian'] = {'Tosk Albanian', 'als'}, -- MediaWiki replaces 'Tosk Albanian' with 'Alemannisch' so 'Tosk Albanian' cannot be found ['valencian'] = {'Valencian', 'ca'}, -- variant of Catalan; categorizes as Catalan } --[[---------------< P R O P E R T I E S _ C A T E G O R I E S >---------------- Properties categories. These are used for investigating qualities of citations. ]] local prop_cats = { ['foreign-lang-source'] = 'CS1 $1-language sources ($2)', -- |language= categories; $1 is foreign-language name, $2 is ISO639-1 code ['foreign-lang-source-2'] = 'CS1 foreign language sources (ISO 639-2)|$1', -- |language= category; a cat for ISO639-2 languages; $1 is the ISO 639-2 code used as a sort key ['jul-greg-uncertainty'] = 'CS1: Julian–Gregorian uncertainty', -- probably temporary cat to identify scope of template with dates 1 October 1582 – 1 January 1926 ['local-lang-source'] = 'CS1 $1-language sources ($2)', -- |language= categories; $1 is local-language name, $2 is ISO639-1 code; not emitted when local_lang_cat_enable is false ['location-test'] = 'CS1 location test', ['long-vol'] = 'CS1: long volume value', -- probably temporary cat to identify scope of |volume= values longer than 4 charachters ['script'] = 'CS1 uses $1-language script ($2)', -- |script-title=xx: has matching category; $1 is language name, $2 is ISO639-1 code ['tracked-param'] = 'CS1 tracked parameter: $1', -- $1 is base (enumerators removed) parameter name ['year-range-abbreviated'] = 'CS1: abbreviated year range', -- probably temporary cat to identify scope of |date=, |year= values using YYYY–YY form } --[[-------------------< T I T L E _ T Y P E S >-------------------------------- Here we map a template's CitationClass to TitleType (default values for |type= parameter) ]] local title_types = { ['AV-media-notes'] = 'Media notes', ['interview'] = 'Interview', ['mailinglist'] = 'Mailing list', ['map'] = 'Map', ['podcast'] = 'Podcast', ['pressrelease'] = 'Press release', ['report'] = 'Report', ['speech'] = 'Speech', ['techreport'] = 'Technical report', ['thesis'] = 'Thesis', } --[[===================<< E R R O R M E S S A G I N G >>====================== ]] --[[----------< E R R O R M E S S A G E S U P P L I M E N T S >------------- I18N for those messages that are supplemented with additional specific text that describes the reason for the error TODO: merge this with special_case_translations{}? ]] local err_msg_supl = { ['char'] = 'invalid character', -- |isbn=, |sbn= ['check'] = 'checksum', -- |isbn=, |sbn= ['flag'] = 'flag', -- |archive-url= ['form'] = 'invalid form', -- |isbn=, |sbn= ['group'] = 'invalid group id', -- |isbn= ['initials'] = 'initials', -- Vancouver ['invalid language code'] = 'invalid language code', -- |script-<param>= ['journal'] = 'journal', -- |bibcode= ['length'] = 'length', -- |isbn=, |bibcode=, |sbn= ['liveweb'] = 'liveweb', -- |archive-url= ['missing comma'] = 'missing comma', -- Vancouver ['missing prefix'] = 'missing prefix', -- |script-<param>= ['missing title part'] = 'missing title part', -- |script-<param>= ['name'] = 'name', -- Vancouver ['non-Latin char'] = 'non-Latin character', -- Vancouver ['path'] = 'path', -- |archive-url= ['prefix'] = 'invalid prefix', -- |isbn= ['punctuation'] = 'punctuation', -- Vancouver ['save'] = 'save command', -- |archive-url= ['suffix'] = 'suffix', -- Vancouver ['timestamp'] = 'timestamp', -- |archive-url= ['unknown language code'] = 'unknown language code', -- |script-<param>= ['value'] = 'value', -- |bibcode= ['year'] = 'year', -- |bibcode= } --[[--------------< E R R O R _ C O N D I T I O N S >--------------------------- Error condition table. This table has two sections: errors at the top, maintenance at the bottom. Maint 'messaging' does not have a 'message' (message=nil) The following contains a list of IDs for various error conditions defined in the code. For each ID, we specify a text message to display, an error category to include, and whether the error message should be wrapped as a hidden comment. Anchor changes require identical changes to matching anchor in Help:CS1 errors TODO: rename error_conditions{} to something more generic; create separate error and maint tables inside that? ]] local error_conditions = { err_accessdate_missing_url = { message = '<code class="cs1-code">&#124;access-date=</code> requires <code class="cs1-code">&#124;url=</code>', anchor = 'accessdate_missing_url', category = 'CS1 errors: access-date without URL', hidden = false }, err_apostrophe_markup = { message = 'Italic or bold markup not allowed in: <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'apostrophe_markup', category = 'CS1 errors: markup', hidden = false }, err_archive_missing_date = { message = '<code class="cs1-code">&#124;archive-url=</code> requires <code class="cs1-code">&#124;archive-date=</code>', anchor = 'archive_missing_date', category = 'CS1 errors: archive-url', hidden = false }, err_archive_missing_url = { message = '<code class="cs1-code">&#124;archive-url=</code> requires <code class="cs1-code">&#124;url=</code>', anchor = 'archive_missing_url', category = 'CS1 errors: archive-url', hidden = false }, err_archive_url = { message = '<code class="cs1-code">&#124;archive-url=</code> is malformed: $1', -- $1 is error message detail anchor = 'archive_url', category = 'CS1 errors: archive-url', hidden = false }, err_arxiv_missing = { message = '<code class="cs1-code">&#124;arxiv=</code> required', anchor = 'arxiv_missing', category = 'CS1 errors: arXiv', -- same as bad arxiv hidden = false }, err_asintld_missing_asin = { message = '<code class="cs1-code">&#124;$1=</code> requires <code class="cs1-code">&#124;asin=</code>', -- $1 is parameter name anchor = 'asintld_missing_asin', category = 'CS1 errors: ASIN TLD', hidden = false }, err_bad_arxiv = { message = 'Check <code class="cs1-code">&#124;arxiv=</code> value', anchor = 'bad_arxiv', category = 'CS1 errors: arXiv', hidden = false }, err_bad_asin = { message = 'Check <code class="cs1-code">&#124;asin=</code> value', anchor = 'bad_asin', category ='CS1 errors: ASIN', hidden = false }, err_bad_asin_tld = { message = 'Check <code class="cs1-code">&#124;asin-tld=</code> value', anchor = 'bad_asin_tld', category ='CS1 errors: ASIN TLD', hidden = false }, err_bad_bibcode = { message = 'Check <code class="cs1-code">&#124;bibcode=</code> $1', -- $1 is error message detail anchor = 'bad_bibcode', category = 'CS1 errors: bibcode', hidden = false }, err_bad_biorxiv = { message = 'Check <code class="cs1-code">&#124;biorxiv=</code> value', anchor = 'bad_biorxiv', category = 'CS1 errors: bioRxiv', hidden = false }, err_bad_citeseerx = { message = 'Check <code class="cs1-code">&#124;citeseerx=</code> value', anchor = 'bad_citeseerx', category = 'CS1 errors: citeseerx', hidden = false }, err_bad_date = { message = 'Check date values in: $1', -- $1 is a parameter name list anchor = 'bad_date', category = 'CS1 errors: dates', hidden = false }, err_bad_doi = { message = 'Check <code class="cs1-code">&#124;doi=</code> value', anchor = 'bad_doi', category = 'CS1 errors: DOI', hidden = false }, err_bad_hdl = { message = 'Check <code class="cs1-code">&#124;hdl=</code> value', anchor = 'bad_hdl', category = 'CS1 errors: HDL', hidden = false }, err_bad_isbn = { message = 'Check <code class="cs1-code">&#124;isbn=</code> value: $1', -- $1 is error message detail anchor = 'bad_isbn', category = 'CS1 errors: ISBN', hidden = false }, err_bad_ismn = { message = 'Check <code class="cs1-code">&#124;ismn=</code> value', anchor = 'bad_ismn', category = 'CS1 errors: ISMN', hidden = false }, err_bad_issn = { message = 'Check <code class="cs1-code">&#124;$1issn=</code> value', -- $1 is 'e' or '' for eissn or issn anchor = 'bad_issn', category = 'CS1 errors: ISSN', hidden = false }, err_bad_jfm = { message = 'Check <code class="cs1-code">&#124;jfm=</code> value', anchor = 'bad_jfm', category = 'CS1 errors: JFM', hidden = false }, err_bad_jstor = { message = 'Check <code class="cs1-code">&#124;jstor=</code> value', anchor = 'bad_jstor', category = 'CS1 errors: JSTOR', hidden = false }, err_bad_lccn = { message = 'Check <code class="cs1-code">&#124;lccn=</code> value', anchor = 'bad_lccn', category = 'CS1 errors: LCCN', hidden = false }, err_bad_mr = { message = 'Check <code class="cs1-code">&#124;mr=</code> value', anchor = 'bad_mr', category = 'CS1 errors: MR', hidden = false }, err_bad_oclc = { message = 'Check <code class="cs1-code">&#124;oclc=</code> value', anchor = 'bad_oclc', category = 'CS1 errors: OCLC', hidden = false }, err_bad_ol = { message = 'Check <code class="cs1-code">&#124;ol=</code> value', anchor = 'bad_ol', category = 'CS1 errors: OL', hidden = false }, err_bad_osti = { message = 'Check <code class="cs1-code">&#124;osti=</code> value', anchor = 'bad_osti', category = 'CS1 errors: OSTI', hidden = false }, err_bad_paramlink = { -- for |title-link=, |author/editor/translator-link=, |series-link=, |episode-link= message = 'Check <code class="cs1-code">&#124;$1=</code> value', -- $1 is parameter name anchor = 'bad_paramlink', category = 'CS1 errors: parameter link', hidden = false }, err_bad_pmc = { message = 'Check <code class="cs1-code">&#124;pmc=</code> value', anchor = 'bad_pmc', category = 'CS1 errors: PMC', hidden = false }, err_bad_pmid = { message = 'Check <code class="cs1-code">&#124;pmid=</code> value', anchor = 'bad_pmid', category = 'CS1 errors: PMID', hidden = false }, err_bad_rfc = { message = 'Check <code class="cs1-code">&#124;rfc=</code> value', anchor = 'bad_rfc', category = 'CS1 errors: RFC', hidden = false }, err_bad_s2cid = { message = 'Check <code class="cs1-code">&#124;s2cid=</code> value', anchor = 'bad_s2cid', category = 'CS1 errors: S2CID', hidden = false }, err_bad_sbn = { message = 'Check <code class="cs1-code">&#124;sbn=</code> value: $1', -- $1 is error message detail anchor = 'bad_sbn', category = 'CS1 errors: SBN', hidden = false }, err_bad_ssrn = { message = 'Check <code class="cs1-code">&#124;ssrn=</code> value', anchor = 'bad_ssrn', category = 'CS1 errors: SSRN', hidden = false }, err_bad_url = { message = 'Check $1 value', -- $1 is parameter name anchor = 'bad_url', category = 'CS1 errors: URL', hidden = false }, err_bad_usenet_id = { message = 'Check <code class="cs1-code">&#124;message-id=</code> value', anchor = 'bad_message_id', category = 'CS1 errors: message-id', hidden = false }, err_bad_zbl = { message = 'Check <code class="cs1-code">&#124;zbl=</code> value', anchor = 'bad_zbl', category = 'CS1 errors: Zbl', hidden = false }, err_bare_url_missing_title = { message = '$1 missing title', -- $1 is parameter name anchor = 'bare_url_missing_title', category = 'CS1 errors: bare URL', hidden = false }, err_biorxiv_missing = { message = '<code class="cs1-code">&#124;biorxiv=</code> required', anchor = 'biorxiv_missing', category = 'CS1 errors: bioRxiv', -- same as bad bioRxiv hidden = false }, err_chapter_ignored = { message = '<code class="cs1-code">&#124;$1=</code> ignored', -- $1 is parameter name anchor = 'chapter_ignored', category = 'CS1 errors: chapter ignored', hidden = false }, err_citation_missing_title = { message = 'Missing or empty <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'citation_missing_title', category = 'CS1 errors: missing title', hidden = false }, err_citeseerx_missing = { message = '<code class="cs1-code">&#124;citeseerx=</code> required', anchor = 'citeseerx_missing', category = 'CS1 errors: citeseerx', -- same as bad citeseerx hidden = false }, err_cite_web_url = { -- this error applies to cite web and to cite podcast message = 'Missing or empty <code class="cs1-code">&#124;url=</code>', anchor = 'cite_web_url', category = 'CS1 errors: requires URL', hidden = false }, err_class_ignored = { message = '<code class="cs1-code">&#124;class=</code> ignored', anchor = 'class_ignored', category = 'CS1 errors: class', hidden = false }, err_contributor_ignored = { message = '<code class="cs1-code">&#124;contributor=</code> ignored', anchor = 'contributor_ignored', category = 'CS1 errors: contributor', hidden = false }, err_contributor_missing_required_param = { message = '<code class="cs1-code">&#124;contributor=</code> requires <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'contributor_missing_required_param', category = 'CS1 errors: contributor', hidden = false }, err_deprecated_params = { message = 'Cite uses deprecated parameter <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'deprecated_params', category = 'CS1 errors: deprecated parameters', hidden = false }, err_disp_name = { message = 'Invalid <code class="cs1-code">&#124;$1=$2</code>', -- $1 is parameter name; $2 is the assigned value anchor = 'disp_name', category = 'CS1 errors: display-names', hidden = false, }, err_doibroken_missing_doi = { message = '<code class="cs1-code">&#124;$1=</code> requires <code class="cs1-code">&#124;doi=</code>', -- $1 is parameter name anchor = 'doibroken_missing_doi', category = 'CS1 errors: DOI', hidden = false }, err_embargo_missing_pmc = { message = '<code class="cs1-code">&#124;$1=</code> requires <code class="cs1-code">&#124;pmc=</code>', -- $1 is parameter name anchor = 'embargo_missing_pmc', category = 'CS1 errors: PMC embargo', hidden = false }, err_empty_citation = { message = 'Empty citation', anchor = 'empty_citation', category = 'CS1 errors: empty citation', hidden = false }, err_etal = { message = 'Explicit use of et al. in: <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'explicit_et_al', category = 'CS1 errors: explicit use of et al.', hidden = false }, err_extra_text_edition = { message = '<code class="cs1-code">&#124;edition=</code> has extra text', anchor = 'extra_text_edition', category = 'CS1 errors: extra text: edition', hidden = false, }, err_extra_text_issue = { message = '<code class="cs1-code">&#124;$1=</code> has extra text', -- $1 is parameter name anchor = 'extra_text_issue', category = 'CS1 errors: extra text: issue', hidden = false, }, err_extra_text_pages = { message = '<code class="cs1-code">&#124;$1=</code> has extra text', -- $1 is parameter name anchor = 'extra_text_pages', category = 'CS1 errors: extra text: pages', hidden = false, }, err_extra_text_volume = { message = '<code class="cs1-code">&#124;$1=</code> has extra text', -- $1 is parameter name anchor = 'extra_text_volume', category = 'CS1 errors: extra text: volume', hidden = true, }, err_first_missing_last = { message = '<code class="cs1-code">&#124;$1=</code> missing <code class="cs1-code">&#124;$2=</code>', -- $1 is first alias, $2 is matching last alias anchor = 'first_missing_last', category = 'CS1 errors: missing name', -- author, contributor, editor, interviewer, translator hidden = false }, err_format_missing_url = { message = '<code class="cs1-code">&#124;$1=</code> requires <code class="cs1-code">&#124;$2=</code>', -- $1 is format parameter $2 is url parameter anchor = 'format_missing_url', category = 'CS1 errors: format without URL', hidden = false }, err_generic_name = { message = '<code class="cs1-code">&#124;$1=</code> has generic name', -- $1 is parameter name anchor = 'generic_name', category = 'CS1 errors: generic name', hidden = false, }, err_generic_title = { message = 'Cite uses generic title', anchor = 'generic_title', category = 'CS1 errors: generic title', hidden = false, }, err_invalid_param_val = { message = 'Invalid <code class="cs1-code">&#124;$1=$2</code>', -- $1 is parameter name $2 is parameter value anchor = 'invalid_param_val', category = 'CS1 errors: invalid parameter value', hidden = false }, err_invisible_char = { message = '$1 in $2 at position $3', -- $1 is invisible char $2 is parameter name $3 is position number anchor = 'invisible_char', category = 'CS1 errors: invisible characters', hidden = false }, err_missing_name = { message = 'Missing <code class="cs1-code">&#124;$1$2=</code>', -- $1 is modified NameList; $2 is enumerator anchor = 'missing_name', category = 'CS1 errors: missing name', -- author, contributor, editor, interviewer, translator hidden = false }, err_missing_periodical = { message = 'Cite $1 requires <code class="cs1-code">&#124;$2=</code>', -- $1 is cs1 template name; $2 is canonical periodical parameter name for cite $1 anchor = 'missing_periodical', category = 'CS1 errors: missing periodical', hidden = true }, err_missing_pipe = { message = 'Missing pipe in: <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'missing_pipe', category = 'CS1 errors: missing pipe', hidden = false }, err_param_access_requires_param = { message = '<code class="cs1-code">&#124;$1-access=</code> requires <code class="cs1-code">&#124;$1=</code>', -- $1 is parameter name anchor = 'param_access_requires_param', category = 'CS1 errors: param-access', hidden = false }, err_param_has_ext_link = { message = 'External link in <code class="cs1-code">$1</code>', -- $1 is parameter name anchor = 'param_has_ext_link', category = 'CS1 errors: external links', hidden = false }, err_parameter_ignored = { message = 'Unknown parameter <code class="cs1-code">&#124;$1=</code> ignored', -- $1 is parameter name anchor = 'parameter_ignored', category = 'CS1 errors: unsupported parameter', hidden = false }, err_parameter_ignored_suggest = { message = 'Unknown parameter <code class="cs1-code">&#124;$1=</code> ignored (<code class="cs1-code">&#124;$2=</code> suggested)', -- $1 is unknown parameter $2 is suggested parameter name anchor = 'parameter_ignored_suggest', category = 'CS1 errors: unsupported parameter', hidden = false }, err_redundant_parameters = { message = 'More than one of $1 specified', -- $1 is error message detail anchor = 'redundant_parameters', category = 'CS1 errors: redundant parameter', hidden = false }, err_script_parameter = { message = 'Invalid <code class="cs1-code">&#124;$1=</code>: $2', -- $1 is parameter name $2 is script language code or error detail anchor = 'script_parameter', category = 'CS1 errors: script parameters', hidden = false }, err_ssrn_missing = { message = '<code class="cs1-code">&#124;ssrn=</code> required', anchor = 'ssrn_missing', category = 'CS1 errors: SSRN', -- same as bad arxiv hidden = false }, err_text_ignored = { message = 'Text "$1" ignored', -- $1 is ignored text anchor = 'text_ignored', category = 'CS1 errors: unrecognized parameter', hidden = false }, err_trans_missing_title = { message = '<code class="cs1-code">&#124;trans-$1=</code> requires <code class="cs1-code">&#124;$1=</code> or <code class="cs1-code">&#124;script-$1=</code>', -- $1 is base parameter name anchor = 'trans_missing_title', category = 'CS1 errors: translated title', hidden = false }, err_param_unknown_empty = { message = 'Cite has empty unknown parameter$1: $2', -- $1 is 's' or empty space; $2 is emty unknown param list anchor = 'param_unknown_empty', category = 'CS1 errors: empty unknown parameters', hidden = false }, err_vancouver = { message = 'Vancouver style error: $1 in name $2', -- $1 is error detail, $2 is the nth name anchor = 'vancouver', category = 'CS1 errors: Vancouver style', hidden = false }, err_wikilink_in_url = { message = 'URL–wikilink conflict', -- uses ndash anchor = 'wikilink_in_url', category = 'CS1 errors: URL–wikilink conflict', -- uses ndash hidden = false }, --[[--------------------------< M A I N T >------------------------------------- maint messages do not have a message (message = nil); otherwise the structure is the same as error messages ]] maint_archived_copy = { message = nil, anchor = 'archived_copy', category = 'CS1 maint: archived copy as title', hidden = true, }, maint_authors = { message = nil, anchor = 'authors', category = 'CS1 maint: uses authors parameter', hidden = true, }, maint_bot_unknown = { message = nil, anchor = 'bot:_unknown', category = 'CS1 maint: bot: original URL status unknown', hidden = true, }, maint_date_auto_xlated = { -- date auto-translation not supported by en.wiki message = nil, anchor = 'date_auto_xlated', category = 'CS1 maint: date auto-translated', hidden = true, }, maint_date_format = { message = nil, anchor = 'date_format', category = 'CS1 maint: date format', hidden = true, }, maint_date_year = { message = nil, anchor = 'date_year', category = 'CS1 maint: date and year', hidden = true, }, maint_doi_ignore = { message = nil, anchor = 'doi_ignore', category = 'CS1 maint: ignored DOI errors', hidden = true, }, maint_doi_inactive = { message = nil, anchor = 'doi_inactive', category = 'CS1 maint: DOI inactive', hidden = true, }, maint_doi_inactive_dated = { message = nil, anchor = 'doi_inactive_dated', category = 'CS1 maint: DOI inactive as of $2$3$1', -- $1 is year, $2 is month-name or empty string, $3 is space or empty string hidden = true, }, maint_extra_punct = { message = nil, anchor = 'extra_punct', category = 'CS1 maint: extra punctuation', hidden = true, }, maint_isbn_ignore = { message = nil, anchor = 'ignore_isbn_err', category = 'CS1 maint: ignored ISBN errors', hidden = true, }, maint_issn_ignore = { message = nil, anchor = 'ignore_issn', category = 'CS1 maint: ignored ISSN errors', hidden = true, }, maint_jfm_format = { message = nil, anchor = 'jfm_format', category = 'CS1 maint: JFM format', hidden = true, }, maint_location = { message = nil, anchor = 'location', category = 'CS1 maint: location', hidden = true, }, maint_mr_format = { message = nil, anchor = 'mr_format', category = 'CS1 maint: MR format', hidden = true, }, maint_mult_names = { message = nil, anchor = 'mult_names', category = 'CS1 maint: multiple names: $1', -- $1 is '<name>s list'; gets value from special_case_translation table hidden = true, }, maint_numeric_names = { message = nil, anchor = 'numeric_names', category = 'CS1 maint: numeric names: $1', -- $1 is '<name>s list'; gets value from special_case_translation table hidden = true, }, maint_others = { message = nil, anchor = 'others', category = 'CS1 maint: others', hidden = true, }, maint_others_avm = { message = nil, anchor = 'others_avm', category = 'CS1 maint: others in cite AV media (notes)', hidden = true, }, maint_pmc_embargo = { message = nil, anchor = 'embargo', category = 'CS1 maint: PMC embargo expired', hidden = true, }, maint_pmc_format = { message = nil, anchor = 'pmc_format', category = 'CS1 maint: PMC format', hidden = true, }, maint_postscript = { message = nil, anchor = 'postscript', category = 'CS1 maint: postscript', hidden = true, }, maint_ref_duplicates_default = { message = nil, anchor = 'ref_default', category = 'CS1 maint: ref duplicates default', hidden = true, }, maint_unfit = { message = nil, anchor = 'unfit', category = 'CS1 maint: unfit URL', hidden = true, }, maint_unknown_lang = { message = nil, anchor = 'unknown_lang', category = 'CS1 maint: unrecognized language', hidden = true, }, maint_untitled = { message = nil, anchor = 'untitled', category = 'CS1 maint: untitled periodical', hidden = true, }, maint_url_status = { message = nil, anchor = 'url_status', category = 'CS1 maint: url-status', hidden = true, }, maint_zbl = { message = nil, anchor = 'zbl', category = 'CS1 maint: Zbl', hidden = true, }, } --[[--------------------------< I D _ H A N D L E R S >-------------------------------------------------------- The following contains a list of values for various defined identifiers. For each identifier we specify a variety of information necessary to properly render the identifier in the citation. parameters: a list of parameter aliases for this identifier; first in the list is the canonical form link: Wikipedia article name redirect: a local redirect to a local Wikipedia article name; at en.wiki, 'ISBN (identifier)' is a redirect to 'International Standard Book Number' q: Wikidata q number for the identifier label: the label preceeding the identifier; label is linked to a Wikipedia article (in this order): redirect from id_handlers['<id>'].redirect when use_identifier_redirects is true Wikidata-supplied article name for the local wiki from id_handlers['<id>'].q local article name from id_handlers['<id>'].link prefix: the first part of a URL that will be concatenated with a second part which usually contains the identifier suffix: optional third part to be added after the identifier encode: true if URI should be percent-encoded; otherwise false COinS: identifier link or keyword for use in COinS: for identifiers registered at info-uri.info use: info:.... where '...' is the appropriate identifier label for identifiers that have COinS keywords, use the keyword: rft.isbn, rft.issn, rft.eissn for |asin= and |ol=, which require assembly, use the keyword: url for others make a URL using the value in prefix/suffix and #label, use the keyword: pre (not checked; any text other than 'info', 'rft', or 'url' works here) set to nil to leave the identifier out of the COinS separator: character or text between label and the identifier in the rendered citation id_limit: for those identifiers with established limits, this property holds the upper limit access: use this parameter to set the access level for all instances of this identifier. the value must be a valid access level for an identifier (see ['id-access'] in this file). custom_access: to enable custom access level for an identifier, set this parameter to the parameter that should control it (normally 'id-access') ]] local id_handlers = { ['ARXIV'] = { parameters = {'arxiv', 'eprint'}, link = 'arXiv', redirect = 'arXiv (identifier)', q = 'Q118398', label = 'arXiv', prefix = '//arxiv.org/abs/', -- protocol-relative tested 2013-09-04 encode = false, COinS = 'info:arxiv', separator = ':', access = 'free', -- free to read }, ['ASIN'] = { parameters = { 'asin', 'ASIN' }, link = 'Amazon Standard Identification Number', redirect = 'ASIN (identifier)', q = 'Q1753278', label = 'ASIN', prefix = '//www.amazon.', COinS = 'url', separator = '&nbsp;', encode = false; }, ['BIBCODE'] = { parameters = {'bibcode'}, link = 'Bibcode', redirect = 'Bibcode (identifier)', q = 'Q25754', label = 'Bibcode', prefix = 'https://ui.adsabs.harvard.edu/abs/', encode = false, COinS = 'info:bibcode', separator = ':', custom_access = 'bibcode-access', }, ['BIORXIV'] = { parameters = {'biorxiv'}, link = 'bioRxiv', redirect = 'bioRxiv (identifier)', q = 'Q19835482', label = 'bioRxiv', prefix = '//doi.org/', COinS = 'pre', -- use prefix value access = 'free', -- free to read encode = true, separator = '&nbsp;', }, ['CITESEERX'] = { parameters = {'citeseerx'}, link = 'CiteSeerX', redirect = 'CiteSeerX (identifier)', q = 'Q2715061', label = 'CiteSeerX', prefix = '//citeseerx.ist.psu.edu/viewdoc/summary?doi=', COinS = 'pre', -- use prefix value access = 'free', -- free to read encode = true, separator = '&nbsp;', }, ['DOI'] = { -- Used by InternetArchiveBot parameters = { 'doi', 'DOI'}, link = 'Digital object identifier', redirect = 'doi (identifier)', q = 'Q25670', label = 'doi', prefix = '//doi.org/', COinS = 'info:doi', separator = ':', encode = true, custom_access = 'doi-access', }, ['EISSN'] = { parameters = {'eissn', 'EISSN'}, link = 'International Standard Serial Number#Electronic ISSN', redirect = 'eISSN (identifier)', q = 'Q46339674', label = 'eISSN', prefix = '//www.worldcat.org/issn/', COinS = 'rft.eissn', encode = false, separator = '&nbsp;', }, ['HDL'] = { parameters = { 'hdl', 'HDL' }, link = 'Handle System', redirect = 'hdl (identifier)', q = 'Q3126718', label = 'hdl', prefix = '//hdl.handle.net/', COinS = 'info:hdl', separator = ':', encode = true, custom_access = 'hdl-access', }, ['ISBN'] = { -- Used by InternetArchiveBot parameters = {'isbn', 'ISBN'}, link = 'International Standard Book Number', redirect = 'ISBN (identifier)', q = 'Q33057', label = 'ISBN', prefix = 'Special:BookSources/', COinS = 'rft.isbn', separator = '&nbsp;', }, ['ISMN'] = { parameters = {'ismn', 'ISMN'}, link = 'International Standard Music Number', redirect = 'ISMN (identifier)', q = 'Q1666938', label = 'ISMN', prefix = '', -- not currently used; COinS = nil, -- nil because we can't use pre or rft or info: separator = '&nbsp;', }, ['ISSN'] = { parameters = {'issn', 'ISSN'}, link = 'International Standard Serial Number', redirect = 'ISSN (identifier)', q = 'Q131276', label = 'ISSN', prefix = '//www.worldcat.org/issn/', COinS = 'rft.issn', encode = false, separator = '&nbsp;', }, ['JFM'] = { parameters = {'jfm', 'JFM'}, link = 'Jahrbuch über die Fortschritte der Mathematik', redirect = 'JFM (identifier)', q = '', label = 'JFM', prefix = '//zbmath.org/?format=complete&q=an:', COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', }, ['JSTOR'] = { parameters = {'jstor', 'JSTOR'}, link = 'JSTOR', redirect = 'JSTOR (identifier)', q = 'Q1420342', label = 'JSTOR', prefix = '//www.jstor.org/stable/', -- protocol-relative tested 2013-09-04 COinS = 'pre', -- use prefix value encode = false, separator = '&nbsp;', custom_access = 'jstor-access', }, ['LCCN'] = { parameters = {'lccn', 'LCCN'}, link = 'Library of Congress Control Number', redirect = 'LCCN (identifier)', q = 'Q620946', label = 'LCCN', prefix = '//lccn.loc.gov/', -- protocol-relative tested 2015-12-28 COinS = 'info:lccn', encode = false, separator = '&nbsp;', }, ['MR'] = { parameters = {'mr', 'MR'}, link = 'Mathematical Reviews', redirect = 'MR (identifier)', q = 'Q211172', label = 'MR', prefix = '//www.ams.org/mathscinet-getitem?mr=', -- protocol-relative tested 2013-09-04 COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', }, ['OCLC'] = { parameters = {'oclc', 'OCLC'}, link = 'OCLC', redirect = 'OCLC (identifier)', q = 'Q190593', label = 'OCLC', prefix = '//www.worldcat.org/oclc/', COinS = 'info:oclcnum', encode = true, separator = '&nbsp;', id_limit = 9999999999, -- 10-digits }, ['OL'] = { parameters = { 'ol', 'OL' }, link = 'Open Library', redirect = 'OL (identifier)', q = 'Q1201876', label = 'OL', prefix = '//openlibrary.org/', COinS = 'url', separator = '&nbsp;', encode = true, custom_access = 'ol-access', }, ['OSTI'] = { parameters = {'osti', 'OSTI'}, link = 'Office of Scientific and Technical Information', redirect = 'OSTI (identifier)', q = 'Q2015776', label = 'OSTI', prefix = '//www.osti.gov/biblio/', -- protocol-relative tested 2018-09-12 COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', id_limit = 23010000, custom_access = 'osti-access', }, ['PMC'] = { parameters = {'pmc', 'PMC'}, link = 'PubMed Central', redirect = 'PMC (identifier)', q = 'Q229883', label = 'PMC', prefix = '//www.ncbi.nlm.nih.gov/pmc/articles/PMC', suffix = '', COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', id_limit = 9500000, access = 'free', -- free to read }, ['PMID'] = { parameters = {'pmid', 'PMID'}, link = 'PubMed Identifier', redirect = 'PMID (identifier)', q = 'Q2082879', label = 'PMID', prefix = '//pubmed.ncbi.nlm.nih.gov/', COinS = 'info:pmid', encode = false, separator = '&nbsp;', id_limit = 36400000, }, ['RFC'] = { parameters = {'rfc', 'RFC'}, link = 'Request for Comments', redirect = 'RFC (identifier)', q = 'Q212971', label = 'RFC', prefix = '//tools.ietf.org/html/rfc', COinS = 'pre', -- use prefix value encode = false, separator = '&nbsp;', id_limit = 9300, access = 'free', -- free to read }, ['SBN'] = { parameters = {'sbn', 'SBN'}, link = 'Standard Book Number', -- redirect to International_Standard_Book_Number#History redirect = 'SBN (identifier)', label = 'SBN', prefix = 'Special:BookSources/0-', -- prefix has leading zero necessary to make 9-digit sbn a 10-digit isbn COinS = nil, -- nil because we can't use pre or rft or info: separator = '&nbsp;', }, ['SSRN'] = { parameters = {'ssrn', 'SSRN'}, link = 'Social Science Research Network', redirect = 'SSRN (identifier)', q = 'Q7550801', label = 'SSRN', prefix = '//ssrn.com/abstract=', -- protocol-relative tested 2013-09-04 COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', id_limit = 4200000, custom_access = 'ssrn-access', }, ['S2CID'] = { parameters = {'s2cid', 'S2CID'}, link = 'Semantic Scholar', redirect = 'S2CID (identifier)', q = 'Q22908627', label = 'S2CID', prefix = 'https://api.semanticscholar.org/CorpusID:', COinS = 'pre', -- use prefix value encode = false, separator = '&nbsp;', id_limit = 254000000, custom_access = 's2cid-access', }, ['USENETID'] = { parameters = {'message-id'}, link = 'Usenet', redirect = 'Usenet (identifier)', q = 'Q193162', label = 'Usenet:', prefix = 'news:', encode = false, COinS = 'pre', -- use prefix value separator = '&nbsp;', }, ['ZBL'] = { parameters = {'zbl', 'ZBL' }, link = 'Zentralblatt MATH', redirect = 'Zbl (identifier)', q = 'Q190269', label = 'Zbl', prefix = '//zbmath.org/?format=complete&q=an:', COinS = 'pre', -- use prefix value encode = true, separator = '&nbsp;', }, } --[[--------------------------< E X P O R T S >--------------------------------- ]] return { use_identifier_redirects = true, -- when true use redirect name for identifier label links; always true at en.wiki local_lang_cat_enable = false; -- when true categorizes pages where |language=<local wiki's language>; always false at en.wiki date_name_auto_xlate_enable = false; -- when true translates English month-names to the local-wiki's language month names; always false at en.wiki date_digit_auto_xlate_enable = false; -- when true translates Western date digit to the local-wiki's language digits (date_names['local_digits']); always false at en.wiki global_df = get_date_format (), -- tables and variables created when this module is loaded punct_skip = build_skip_table (punct_skip, punct_meta_params), url_skip = build_skip_table (url_skip, url_meta_params), aliases = aliases, special_case_translation = special_case_translation, date_names = date_names, err_msg_supl = err_msg_supl, error_conditions = error_conditions, editor_markup_patterns = editor_markup_patterns, et_al_patterns = et_al_patterns, id_handlers = id_handlers, keywords_lists = keywords_lists, keywords_xlate = keywords_xlate, stripmarkers=stripmarkers, invisible_chars = invisible_chars, invisible_defs = invisible_defs, indic_script = indic_script, emoji = emoji, maint_cats = maint_cats, messages = messages, presentation = presentation, prop_cats = prop_cats, script_lang_codes = script_lang_codes, lang_code_remap = lang_code_remap, lang_name_remap = lang_name_remap, this_wiki_code = this_wiki_code, title_types = title_types, uncategorized_namespaces = uncategorized_namespaces, uncategorized_subpages = uncategorized_subpages, templates_using_volume = templates_using_volume, templates_using_issue = templates_using_issue, templates_not_using_page = templates_not_using_page, vol_iss_pg_patterns = vol_iss_pg_patterns, inter_wiki_map = inter_wiki_map, mw_languages_by_tag_t = mw_languages_by_tag_t, mw_languages_by_name_t = mw_languages_by_name_t, citation_class_map_t = citation_class_map_t, citation_issue_t = citation_issue_t, citation_no_volume_t = citation_no_volume_t, } eece11b3085eb39f5bb266336c4c5afa7a6eaa74 Module:Citation/CS1/Whitelist 828 52 120 119 2022-09-04T15:24:35Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[--------------------------< S U P P O R T E D P A R A M E T E R S >-------------------------------------- Because a steady-state signal conveys no useful information, whitelist.basic_arguments[] list items can have three values: true - these parameters are valid and supported parameters false - these parameters are deprecated but still supported tracked - these parameters are valid and supported parameters tracked in an eponymous properties category nil - these parameters are no longer supported. remove entirely ]] local basic_arguments = { ['accessdate'] = true, ['access-date'] = true, ['agency'] = true, ['archivedate'] = true, ['archive-date'] = true, ['archive-format'] = true, ['archiveurl'] = true, ['archive-url'] = true, ['article'] = true, ['article-format'] = true, ['article-url'] = true, ['article-url-access'] = true, ['arxiv'] = true, -- cite arxiv; here because allowed in cite ... as identifier ['asin'] = true, ['ASIN'] = true, ['asin-tld'] = true, ['at'] = true, ['author'] = true, ['author-first'] = true, ['author-given'] = true, ['author-last'] = true, ['author-surname'] = true, ['authorlink'] = true, ['author-link'] = true, ['author-mask'] = true, ['authors'] = true, ['bibcode'] = true, ['bibcode-access'] = true, ['biorxiv'] = true, -- cite biorxiv; here because allowed in cite ... as identifier ['chapter'] = true, ['chapter-format'] = true, ['chapter-url'] = true, ['chapter-url-access'] = true, ['citeseerx'] = true, -- cite citeseerx; here because allowed in cite ... as identifier ['collaboration'] = true, ['contribution'] = true, ['contribution-format'] = true, ['contribution-url'] = true, ['contribution-url-access'] = true, ['contributor'] = true, ['contributor-first'] = true, ['contributor-given'] = true, ['contributor-last'] = true, ['contributor-surname'] = true, ['contributor-link'] = true, ['contributor-mask'] = true, ['date'] = true, ['department'] = true, ['df'] = true, ['dictionary'] = true, ['display-authors'] = true, ['display-contributors'] = true, ['display-editors'] = true, ['display-interviewers'] = true, ['display-subjects'] = true, ['display-translators'] = true, ['doi'] = true, ['DOI'] = true, ['doi-access'] = true, ['doi-broken-date'] = true, ['edition'] = true, ['editor'] = true, ['editor-first'] = true, ['editor-given'] = true, ['editor-last'] = true, ['editor-surname'] = true, ['editor-link'] = true, ['editor-mask'] = true, ['eissn'] = true, ['EISSN'] = true, ['encyclopaedia'] = true, ['encyclopedia'] = true, ['entry'] = true, ['entry-format'] = true, ['entry-url'] = true, ['entry-url-access'] = true, ['eprint'] = true, -- cite arxiv; here because allowed in cite ... as identifier ['first'] = true, ['format'] = true, ['given'] = true, ['hdl'] = true, ['HDL'] = true, ['hdl-access'] = true, ['host'] = true, -- unique to certain templates? ['id'] = true, ['ID'] = true, ['institution'] = true, -- constrain to cite thesis? ['interviewer'] = true, ['interviewer-first'] = true, ['interviewer-given'] = true, ['interviewer-last'] = true, ['interviewer-surname'] = true, ['interviewer-link'] = true, ['interviewer-mask'] = true, ['isbn'] = true, ['ISBN'] = true, ['ismn'] = true, ['ISMN'] = true, ['issn'] = true, ['ISSN'] = true, ['issue'] = true, ['jfm'] = true, ['JFM'] = true, ['journal'] = true, ['jstor'] = true, ['JSTOR'] = true, ['jstor-access'] = true, ['lang'] = true, ['language'] = true, ['last'] = true, ['lay-date'] = false, ['lay-format'] = false, ['lay-source'] = false, ['lay-url'] = false, ['lccn'] = true, ['LCCN'] = true, ['location'] = true, ['magazine'] = true, ['medium'] = true, ['minutes'] = true, -- constrain to cite AV media and podcast? ['mode'] = true, ['mr'] = true, ['MR'] = true, ['name-list-style'] = true, ['newspaper'] = true, ['no-pp'] = true, ['no-tracking'] = true, ['number'] = true, ['oclc'] = true, ['OCLC'] = true, ['ol'] = true, ['OL'] = true, ['ol-access'] = true, ['orig-date'] = true, ['origyear'] = true, ['orig-year'] = true, ['osti'] = true, ['OSTI'] = true, ['osti-access'] = true, ['others'] = true, ['p'] = true, ['page'] = true, ['pages'] = true, ['people'] = true, ['periodical'] = true, ['place'] = true, ['pmc'] = true, ['PMC'] = true, ['pmc-embargo-date'] = true, ['pmid'] = true, ['PMID'] = true, ['postscript'] = true, ['pp'] = true, ['publication-date'] = true, ['publication-place'] = true, ['publisher'] = true, ['quotation'] = true, ['quote'] = true, ['quote-page'] = true, ['quote-pages'] = true, ['ref'] = true, ['rfc'] = true, ['RFC'] = true, ['sbn'] = true, ['SBN'] = true, ['scale'] = true, ['script-article'] = true, ['script-chapter'] = true, ['script-contribution'] = true, ['script-entry'] = true, ['script-journal'] = true, ['script-magazine'] = true, ['script-newspaper'] = true, ['script-periodical'] = true, ['script-quote'] = true, ['script-section'] = true, ['script-title'] = true, ['script-website'] = true, ['script-work'] = true, ['section'] = true, ['section-format'] = true, ['section-url'] = true, ['section-url-access'] = true, ['series'] = true, ['ssrn'] = true, -- cite ssrn; these three here because allowed in cite ... as identifier ['SSRN'] = true, ['ssrn-access'] = true, ['subject'] = true, ['subject-link'] = true, ['subject-mask'] = true, ['surname'] = true, ['s2cid'] = true, ['S2CID'] = true, ['s2cid-access'] = true, ['template-doc-demo'] = true, ['time'] = true, -- constrain to cite av media and podcast? ['time-caption'] = true, -- constrain to cite av media and podcast? ['title'] = true, ['title-link'] = true, ['translator'] = true, ['translator-first'] = true, ['translator-given'] = true, ['translator-last'] = true, ['translator-surname'] = true, ['translator-link'] = true, ['translator-mask'] = true, ['trans-article'] = true, ['trans-chapter'] = true, ['trans-contribution'] = true, ['trans-entry'] = true, ['trans-journal'] = true, ['trans-magazine'] = true, ['trans-newspaper'] = true, ['trans-periodical'] = true, ['trans-quote'] = true, ['trans-section'] = true, ['trans-title'] = true, ['trans-website'] = true, ['trans-work'] = true, ['type'] = true, ['url'] = true, ['URL'] = true, ['url-access'] = true, ['url-status'] = true, ['vauthors'] = true, ['veditors'] = true, ['version'] = true, ['via'] = true, ['volume'] = true, ['website'] = true, ['work'] = true, ['year'] = true, ['zbl'] = true, ['ZBL'] = true, } local numbered_arguments = { ['author#'] = true, ['author-first#'] = true, ['author#-first'] = true, ['author-given#'] = true, ['author#-given'] = true, ['author-last#'] = true, ['author#-last'] = true, ['author-surname#'] = true, ['author#-surname'] = true, ['author-link#'] = true, ['author#-link'] = true, ['authorlink#'] = true, ['author#link'] = true, ['author-mask#'] = true, ['author#-mask'] = true, ['contributor#'] = true, ['contributor-first#'] = true, ['contributor#-first'] = true, ['contributor-given#'] = true, ['contributor#-given'] = true, ['contributor-last#'] = true, ['contributor#-last'] = true, ['contributor-surname#'] = true, ['contributor#-surname'] = true, ['contributor-link#'] = true, ['contributor#-link'] = true, ['contributor-mask#'] = true, ['contributor#-mask'] = true, ['editor#'] = true, ['editor-first#'] = true, ['editor#-first'] = true, ['editor-given#'] = true, ['editor#-given'] = true, ['editor-last#'] = true, ['editor#-last'] = true, ['editor-surname#'] = true, ['editor#-surname'] = true, ['editor-link#'] = true, ['editor#-link'] = true, ['editor-mask#'] = true, ['editor#-mask'] = true, ['first#'] = true, ['given#'] = true, ['host#'] = true, ['interviewer#'] = true, ['interviewer-first#'] = true, ['interviewer#-first'] = true, ['interviewer-given#'] = true, ['interviewer#-given'] = true, ['interviewer-last#'] = true, ['interviewer#-last'] = true, ['interviewer-surname#'] = true, ['interviewer#-surname'] = true, ['interviewer-link#'] = true, ['interviewer#-link'] = true, ['interviewer-mask#'] = true, ['interviewer#-mask'] = true, ['last#'] = true, ['subject#'] = true, ['subject-link#'] = true, ['subject#-link'] = true, ['subject-mask#'] = true, ['subject#-mask'] = true, ['surname#'] = true, ['translator#'] = true, ['translator-first#'] = true, ['translator#-first'] = true, ['translator-given#'] = true, ['translator#-given'] = true, ['translator-last#'] = true, ['translator#-last'] = true, ['translator-surname#'] = true, ['translator#-surname'] = true, ['translator-link#'] = true, ['translator#-link'] = true, ['translator-mask#'] = true, ['translator#-mask'] = true, } --[[--------------------------< P R E P R I N T S U P P O R T E D P A R A M E T E R S >-------------------- Cite arXiv, cite biorxiv, cite citeseerx, and cite ssrn are preprint templates that use the limited set of parameters defined in the limited_basic_arguments and limited_numbered_arguments tables. Those lists are supplemented with a template-specific list of parameters that are required by the particular template and may be exclusive to one of the preprint templates. Some of these parameters may also be available to the general cs1|2 templates. Same conventions for true/false/tracked/nil as above. ]] local preprint_arguments = { arxiv = { ['arxiv'] = true, -- cite arxiv and arxiv identifiers ['class'] = true, ['eprint'] = true, -- cite arxiv and arxiv identifiers }, biorxiv = { ['biorxiv'] = true, }, citeseerx = { ['citeseerx'] = true, }, ssrn = { ['ssrn'] = true, ['SSRN'] = true, ['ssrn-access'] = true, }, } --[[--------------------------< L I M I T E D S U P P O R T E D P A R A M E T E R S >---------------------- cite arxiv, cite biorxiv, cite citeseerx, and cite ssrn templates are preprint templates so are allowed only a limited subset of parameters allowed to all other cs1|2 templates. The limited subset is defined here. Same conventions for true/false/tracked/nil as above. ]] local limited_basic_arguments = { ['at'] = true, ['author'] = true, ['author-first'] = true, ['author-given'] = true, ['author-last'] = true, ['author-surname'] = true, ['author-link'] = true, ['authorlink'] = true, ['author-mask'] = true, ['authors'] = true, ['collaboration'] = true, ['date'] = true, ['df'] = true, ['display-authors'] = true, ['first'] = true, ['given'] = true, ['language'] = true, ['last'] = true, ['mode'] = true, ['name-list-style'] = true, ['no-tracking'] = true, ['p'] = true, ['page'] = true, ['pages'] = true, ['postscript'] = true, ['pp'] = true, ['quotation'] = true, ['quote'] = true, ['ref'] = true, ['surname'] = true, ['template-doc-demo'] = true, ['title'] = true, ['trans-title'] = true, ['vauthors'] = true, ['year'] = true, } local limited_numbered_arguments = { ['author#'] = true, ['author-first#'] = true, ['author#-first'] = true, ['author-given#'] = true, ['author#-given'] = true, ['author-last#'] = true, ['author#-last'] = true, ['author-surname#'] = true, ['author#-surname'] = true, ['author-link#'] = true, ['author#-link'] = true, ['authorlink#'] = true, ['author#link'] = true, ['author-mask#'] = true, ['author#-mask'] = true, ['first#'] = true, ['given#'] = true, ['last#'] = true, ['surname#'] = true, } --[[--------------------------< U N I Q U E _ A R G U M E N T S >---------------------------------------------- Some templates have unique parameters. Those templates and their unique parameters are listed here. Keys in this table are the template's CitationClass parameter value Same conventions for true/false/tracked/nil as above. ]] local unique_arguments = { ['audio-visual'] = { ['transcript'] = true, ['transcript-format'] = true, ['transcript-url'] = true, }, conference = { ['book-title'] = true, ['conference'] = true, ['conference-format'] = true, ['conference-url'] = true, ['event'] = true, }, episode = { ['airdate'] = true, ['air-date'] = true, ['credits'] = true, ['episode-link'] = true, -- alias of |title-link= ['network'] = true, ['season'] = true, ['series-link'] = true, ['series-no'] = true, ['series-number'] = true, ['station'] = true, ['transcript'] = true, ['transcript-format'] = true, ['transcripturl'] = false, ['transcript-url'] = true, }, mailinglist = { ['mailing-list'] = true, }, map = { ['cartography'] = true, ['inset'] = true, ['map'] = true, ['map-format'] = true, ['map-url'] = true, ['map-url-access'] = true, ['script-map'] = true, ['sections'] = true, ['sheet'] = true, ['sheets'] = true, ['trans-map'] = true, }, newsgroup = { ['message-id'] = true, ['newsgroup'] = true, }, report = { ['docket'] = true, }, serial = { ['airdate'] = true, ['air-date'] = true, ['credits'] = true, ['episode'] = true, -- cite serial only TODO: make available to cite episode? ['episode-link'] = true, -- alias of |title-link= ['network'] = true, ['series-link'] = true, ['station'] = true, }, speech = { ['conference'] = true, ['conference-format'] = true, ['conference-url'] = true, ['event'] = true, }, thesis = { ['degree'] = true, ['docket'] = true, }, } --[[--------------------------< T E M P L A T E _ L I S T _ G E T >-------------------------------------------- gets a list of the templates from table t ]] local function template_list_get (t) local out = {}; -- a table for output for k, _ in pairs (t) do -- spin through the table and collect the keys table.insert (out, k) -- add each key to the output table end return out; -- and done end --[[--------------------------< E X P O R T E D T A B L E S >------------------------------------------------ ]] return { basic_arguments = basic_arguments, numbered_arguments = numbered_arguments, limited_basic_arguments = limited_basic_arguments, limited_numbered_arguments = limited_numbered_arguments, preprint_arguments = preprint_arguments, preprint_template_list = template_list_get (preprint_arguments), -- make a template list from preprint_arguments{} table unique_arguments = unique_arguments, unique_param_template_list = template_list_get (unique_arguments), -- make a template list from unique_arguments{} table }; 6773846564c816e7f9eae451b65436cbda849bc5 Module:Citation/CS1/Utilities 828 53 122 121 2022-09-04T15:24:35Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local z = { error_cats_t = {}; -- for categorizing citations that contain errors error_ids_t = {}; -- list of error identifiers; used to prevent duplication of certain errors; local to this module error_msgs_t = {}; -- sequence table of error messages maint_cats_t = {}; -- for categorizing citations that aren't erroneous per se, but could use a little work prop_cats_t = {}; -- for categorizing citations based on certain properties, language of source for instance prop_keys_t = {}; -- for adding classes to the citation's <cite> tag }; --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration --[[--------------------------< I S _ S E T >------------------------------------------------------------------ Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string. ]] local function is_set (var) return not (var == nil or var == ''); end --[[--------------------------< I N _ A R R A Y >-------------------------------------------------------------- Whether needle is in haystack ]] local function in_array (needle, haystack) if needle == nil then return false; end for n, v in ipairs (haystack) do if v == needle then return n; end end return false; end --[[--------------------------< H A S _ A C C E P T _ A S _ W R I T T E N >------------------------------------ When <str> is wholly wrapped in accept-as-written markup, return <str> without markup and true; return <str> and false else with allow_empty = false, <str> must have at least one character inside the markup with allow_empty = true, <str> the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition "has no applicable value" in citation-context. After further evaluation the two cases might be merged at a later stage, but should be kept separated for now. ]] local function has_accept_as_written (str, allow_empty) if not is_set (str) then return str, false; end local count; if true == allow_empty then str, count = str:gsub ('^%(%((.*)%)%)$', '%1'); -- allows (()) to be an empty set else str, count = str:gsub ('^%(%((.+)%)%)$', '%1'); end return str, 0 ~= count; end --[[--------------------------< S U B S T I T U T E >---------------------------------------------------------- Populates numbered arguments in a message string using an argument table. <args> may be a single string or a sequence table of multiple strings. ]] local function substitute (msg, args) return args and mw.message.newRawMessage (msg, args):plain() or msg; end --[[--------------------------< E R R O R _ C O M M E N T >---------------------------------------------------- Wraps error messages with CSS markup according to the state of hidden. <content> may be a single string or a sequence table of multiple strings. ]] local function error_comment (content, hidden) return substitute (hidden and cfg.presentation['hidden-error'] or cfg.presentation['visible-error'], content); end --[[--------------------------< H Y P H E N _ T O _ D A S H >-------------------------------------------------- Converts a hyphen to a dash under certain conditions. The hyphen must separate like items; unlike items are returned unmodified. These forms are modified: letter - letter (A - B) digit - digit (4-5) digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5) letterdigit - letterdigit (A1-A5) (an optional separator between letter and digit is supported – a.1-a.5 or a-1-a-5) digitletter - digitletter (5a - 5d) (an optional separator between letter and digit is supported – 5.a-5.d or 5-a-5-d) any other forms are returned unmodified. str may be a comma- or semicolon-separated list ]] local function hyphen_to_dash (str) if not is_set (str) then return str; end local accept; -- boolean str = str:gsub ("(%(%(.-%)%))", function(m) return m:gsub(",", ","):gsub(";", ";") end) -- replace commas and semicolons in accept-as-written markup with similar unicode characters so they'll be ignored during the split str = str:gsub ('&[nm]dash;', {['&ndash;'] = '–', ['&mdash;'] = '—'}); -- replace &mdash; and &ndash; entities with their characters; semicolon mucks up the text.split str = str:gsub ('&#45;', '-'); -- replace HTML numeric entity with hyphen character str = str:gsub ('&nbsp;', ' '); -- replace &nbsp; entity with generic keyboard space character local out = {}; local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any for _, item in ipairs (list) do -- for each item in the list item, accept = has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators if item:match ('^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$') or -- letterdigit hyphen letterdigit (optional separator between letter and digit) item:match ('^%d+[%.%-]?%a+%s*%-%s*%d+[%.%-]?%a+$') or -- digitletter hyphen digitletter (optional separator between digit and letter) item:match ('^%d+[%.%-]%d+%s*%-%s*%d+[%.%-]%d+$') or -- digit separator digit hyphen digit separator digit item:match ('^%d+%s*%-%s*%d+$') or -- digit hyphen digit item:match ('^%a+%s*%-%s*%a+$') then -- letter hyphen letter item = item:gsub ('(%w*[%.%-]?%w+)%s*%-%s*(%w*[%.%-]?%w+)', '%1–%2'); -- replace hyphen, remove extraneous space characters else item = mw.ustring.gsub (item, '%s*[–—]%s*', '–'); -- for endash or emdash separated ranges, replace em with en, remove extraneous whitespace end end table.insert (out, item); -- add the (possibly modified) item to the output table end local temp_str = ''; -- concatenate the output table into a comma separated string temp_str, accept = has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out if accept then temp_str = has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value return temp_str:gsub(",", ","):gsub(";", ";"); else return temp_str:gsub(",", ","):gsub(";", ";"); -- else, return assembled temp_str end end --[=[-------------------------< M A K E _ W I K I L I N K >---------------------------------------------------- Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only link is provided (or link and display are the same), returns a wikilink in the form [[L]]; if neither are provided or link is omitted, returns an empty string. ]=] local function make_wikilink (link, display) if not is_set (link) then return '' end if is_set (display) and link ~= display then return table.concat ({'[[', link, '|', display, ']]'}); else return table.concat ({'[[', link, ']]'}); end end --[[--------------------------< S E T _ M E S S A G E >---------------------------------------------------------- Sets an error message using the ~/Configuration error_conditions{} table along with arguments supplied in the function call, inserts the resulting message in z.error_msgs_t{} sequence table, and returns the error message. <error_id> – key value for appropriate error handler in ~/Configuration error_conditions{} table <arguments> – may be a single string or a sequence table of multiple strings to be subsititued into error_conditions[error_id].message <raw> – boolean true – causes this function to return the error message not wrapped in visible-error, hidden-error span tag; returns error_conditions[error_id].hidden as a second return value does not add message to z.error_msgs_t sequence table false, nil – adds message wrapped in visible-error, hidden-error span tag to z.error_msgs_t returns the error message wrapped in visible-error, hidden-error span tag; there is no second return value <prefix> – string to be prepended to <message> -- TODO: remove support for these unused(?) arguments? <suffix> – string to be appended to <message> TODO: change z.error_cats_t and z.maint_cats_t to have the form cat_name = true? this to avoid dups without having to have an extra table ]] local added_maint_cats = {} -- list of maintenance categories that have been added to z.maint_cats_t; TODO: figure out how to delete this table local function set_message (error_id, arguments, raw, prefix, suffix) local error_state = cfg.error_conditions[error_id]; prefix = prefix or ''; suffix = suffix or ''; if error_state == nil then error (cfg.messages['undefined_error'] .. ': ' .. error_id); -- because missing error handler in Module:Citation/CS1/Configuration elseif is_set (error_state.category) then if error_state.message then -- when error_state.message defined, this is an error message table.insert (z.error_cats_t, error_state.category); else if not added_maint_cats[error_id] then added_maint_cats[error_id] = true; -- note that we've added this category table.insert (z.maint_cats_t, substitute (error_state.category, arguments)); -- make cat name then add to table end return; -- because no message, nothing more to do end end local message = substitute (error_state.message, arguments); message = table.concat ( { message, ' (', make_wikilink ( table.concat ( { cfg.messages['help page link'], '#', error_state.anchor }), cfg.messages['help page label']), ')' }); z.error_ids_t[error_id] = true; if z.error_ids_t['err_citation_missing_title'] and -- if missing-title error already noted in_array (error_id, {'err_bare_url_missing_title', 'err_trans_missing_title'}) then -- and this error is one of these return '', false; -- don't bother because one flavor of missing title is sufficient end message = table.concat ({prefix, message, suffix}); if true == raw then return message, error_state.hidden; -- return message not wrapped in visible-error, hidden-error span tag end message = error_comment (message, error_state.hidden); -- wrap message in visible-error, hidden-error span tag table.insert (z.error_msgs_t, message); -- add it to the messages sequence table return message; -- and done; return value generally not used but is used as a flag in various functions of ~/Identifiers end --[[-------------------------< I S _ A L I A S _ U S E D >----------------------------------------------------- This function is used by select_one() to determine if one of a list of alias parameters is in the argument list provided by the template. Input: args – pointer to the arguments table from calling template alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration index – for enumerated parameters, identifies which one enumerated – true/false flag used to choose how enumerated aliases are examined value – value associated with an alias that has previously been selected; nil if not yet selected selected – the alias that has previously been selected; nil if not yet selected error_list – list of aliases that are duplicates of the alias already selected Returns: value – value associated with alias we selected or that was previously selected or nil if an alias not yet selected selected – the alias we selected or the alias that was previously selected or nil if an alias not yet selected ]] local function is_alias_used (args, alias, index, enumerated, value, selected, error_list) if enumerated then -- is this a test for an enumerated parameters? alias = alias:gsub ('#', index); -- replace '#' with the value in index else alias = alias:gsub ('#', ''); -- remove '#' if it exists end if is_set (args[alias]) then -- alias is in the template's argument list if value ~= nil and selected ~= alias then -- if we have already selected one of the aliases local skip; for _, v in ipairs (error_list) do -- spin through the error list to see if we've added this alias if v == alias then skip = true; break; -- has been added so stop looking end end if not skip then -- has not been added so table.insert (error_list, alias); -- add error alias to the error list end else value = args[alias]; -- not yet selected an alias, so select this one selected = alias; end end return value, selected; -- return newly selected alias, or previously selected alias end --[[--------------------------< A D D _ M A I N T _ C A T >------------------------------------------------------ Adds a category to z.maint_cats_t using names from the configuration file with additional text if any. To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maint_cats_t. ]] local function add_maint_cat (key, arguments) if not added_maint_cats [key] then added_maint_cats [key] = true; -- note that we've added this category table.insert (z.maint_cats_t, substitute (cfg.maint_cats [key], arguments)); -- make name then add to table end end --[[--------------------------< A D D _ P R O P _ C A T >-------------------------------------------------------- Adds a category to z.prop_cats_t using names from the configuration file with additional text if any. foreign_lang_source and foreign_lang_source_2 keys have a language code appended to them so that multiple languages may be categorized but multiples of the same language are not categorized. added_prop_cats is a table declared in page scope variables above ]] local added_prop_cats = {}; -- list of property categories that have been added to z.prop_cats_t local function add_prop_cat (key, arguments, key_modifier) local key_modified = key .. ((key_modifier and key_modifier) or ''); -- modify <key> with <key_modifier> if present and not nil if not added_prop_cats [key_modified] then added_prop_cats [key_modified] = true; -- note that we've added this category table.insert (z.prop_cats_t, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table table.insert (z.prop_keys_t, 'cs1-prop-' .. key); -- convert key to class for use in the citation's <cite> tag end end --[[--------------------------< S A F E _ F O R _ I T A L I C S >---------------------------------------------- Protects a string that will be wrapped in wiki italic markup '' ... '' Note: We cannot use <i> for italics, as the expected behavior for italics specified by ''...'' in the title is that they will be inverted (i.e. unitalicized) in the resulting references. In addition, <i> and '' tend to interact poorly under Mediawiki's HTML tidy. ]] local function safe_for_italics (str) if not is_set (str) then return str end if str:sub (1, 1) == "'" then str = "<span></span>" .. str; end if str:sub (-1, -1) == "'" then str = str .. "<span></span>"; end return str:gsub ('\n', ' '); -- Remove newlines as they break italics. end --[[--------------------------< W R A P _ S T Y L E >---------------------------------------------------------- Applies styling to various parameters. Supplied string is wrapped using a message_list configuration taking one argument; protects italic styled parameters. Additional text taken from citation_config.presentation - the reason this function is similar to but separate from wrap_msg(). ]] local function wrap_style (key, str) if not is_set (str) then return ""; elseif in_array (key, {'italic-title', 'trans-italic-title'}) then str = safe_for_italics (str); end return substitute (cfg.presentation[key], {str}); end --[[--------------------------< M A K E _ S E P _ L I S T >------------------------------------------------------------ make a separated list of items using provided separators. <sep_list> - typically '<comma><space>' <sep_list_pair> - typically '<space>and<space>' <sep_list_end> - typically '<comma><space>and<space>' or '<comma><space>&<space>' defaults to cfg.presentation['sep_list'], cfg.presentation['sep_list_pair'], and cfg.presentation['sep_list_end'] if <sep_list_end> is specified, <sep_list> and <sep_list_pair> must also be supplied ]] local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end) local list = ''; if not sep_list then -- set the defaults sep_list = cfg.presentation['sep_list']; sep_list_pair = cfg.presentation['sep_list_pair']; sep_list_end = cfg.presentation['sep_list_end']; end if 2 >= count then list = table.concat (list_seq, sep_list_pair); -- insert separator between two items; returns list_seq[1] then only one item elseif 2 < count then list = table.concat (list_seq, sep_list, 1, count - 1); -- concatenate all but last item with plain list separator list = table.concat ({list, list_seq[count]}, sep_list_end); -- concatenate last item onto end of <list> with final separator end return list; end --[[--------------------------< S E L E C T _ O N E >---------------------------------------------------------- Chooses one matching parameter from a list of parameters to consider. The list of parameters to consider is just names. For parameters that may be enumerated, the position of the numerator in the parameter name is identified by the '#' so |author-last1= and |author1-last= are represented as 'author-last#' and 'author#-last'. Because enumerated parameter |<param>1= is an alias of |<param>= we must test for both possibilities. Generates an error if more than one match is present. ]] local function select_one (args, aliases_list, error_condition, index) local value = nil; -- the value assigned to the selected parameter local selected = ''; -- the name of the parameter we have chosen local error_list = {}; if index ~= nil then index = tostring(index); end for _, alias in ipairs (aliases_list) do -- for each alias in the aliases list if alias:match ('#') then -- if this alias can be enumerated if '1' == index then -- when index is 1 test for enumerated and non-enumerated aliases value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- first test for non-enumerated alias end value, selected = is_alias_used (args, alias, index, true, value, selected, error_list); -- test for enumerated alias else value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- test for non-enumerated alias end end if #error_list > 0 and 'none' ~= error_condition then -- for cases where this code is used outside of extract_names() for i, v in ipairs (error_list) do error_list[i] = wrap_style ('parameter', v); end table.insert (error_list, wrap_style ('parameter', selected)); set_message (error_condition, {make_sep_list (#error_list, error_list)}); end return value, selected; end --[=[-------------------------< R E M O V E _ W I K I _ L I N K >---------------------------------------------- Gets the display text from a wikilink like [[A|B]] or [[B]] gives B The str:gsub() returns either A|B froma [[A|B]] or B from [[B]] or B from B (no wikilink markup). In l(), l:gsub() removes the link and pipe (if they exist); the second :gsub() trims whitespace from the label if str was wrapped in wikilink markup. Presumably, this is because without wikimarkup in str, there is no match in the initial gsub, the replacement function l() doesn't get called. ]=] local function remove_wiki_link (str) return (str:gsub ("%[%[([^%[%]]*)%]%]", function(l) return l:gsub ("^[^|]*|(.*)$", "%1" ):gsub ("^%s*(.-)%s*$", "%1"); end)); end --[=[-------------------------< I S _ W I K I L I N K >-------------------------------------------------------- Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts. If str is a complex wikilink ([[L|D]]): returns wl_type 2 and D and L from [[L|D]]; if str is a simple wikilink ([[D]]) returns wl_type 1 and D from [[D]] and L as empty string; if not a wikilink: returns wl_type 0, str as D, and L as empty string. trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes). ]=] local function is_wikilink (str) local D, L local wl_type = 2; -- assume that str is a complex wikilink [[L|D]] if not str:match ('^%[%[[^%]]+%]%]$') then -- is str some sort of a wikilink (must have some sort of content) return 0, str, ''; -- not a wikilink; return wl_type as 0, str as D, and empty string as L end L, D = str:match ('^%[%[([^|]+)|([^%]]+)%]%]$'); -- get L and D from [[L|D]] if not is_set (D) then -- if no separate display D = str:match ('^%[%[([^%]]*)|*%]%]$'); -- get D from [[D]] or [[D|]] wl_type = 1; end D = mw.text.trim (D, '%s|'); -- trim white space and pipe characters return wl_type, D, L or ''; end --[[--------------------------< S T R I P _ A P O S T R O P H E _ M A R K U P >-------------------------------- Strip wiki italic and bold markup from argument so that it doesn't contaminate COinS metadata. This function strips common patterns of apostrophe markup. We presume that editors who have taken the time to markup a title have, as a result, provided valid markup. When they don't, some single apostrophes are left behind. Returns the argument without wiki markup and a number; the number is more-or-less meaningless except as a flag to indicate that markup was replaced; do not rely on it as an indicator of how many of any kind of markup was removed; returns the argument and nil when no markup removed ]] local function strip_apostrophe_markup (argument) if not is_set (argument) then return argument, nil; -- no argument, nothing to do end if nil == argument:find ( "''", 1, true ) then -- Is there at least one double apostrophe? If not, exit. return argument, nil; end local flag; while true do if argument:find ("'''''", 1, true) then -- bold italic (5) argument, flag = argument:gsub ("%'%'%'%'%'", ""); -- remove all instances of it elseif argument:find ("''''", 1, true) then -- italic start and end without content (4) argument, flag=argument:gsub ("%'%'%'%'", ""); elseif argument:find ("'''", 1, true) then -- bold (3) argument, flag=argument:gsub ("%'%'%'", ""); elseif argument:find ("''", 1, true) then -- italic (2) argument, flag = argument:gsub ("%'%'", ""); else break; end end return argument, flag; -- done end --[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >-------------------------------------- Sets local cfg table to same (live or sandbox) as that used by the other modules. ]] local function set_selected_modules (cfg_table_ptr) cfg = cfg_table_ptr; end --[[--------------------------< E X P O R T S >---------------------------------------------------------------- ]] return { add_maint_cat = add_maint_cat, -- exported functions add_prop_cat = add_prop_cat, error_comment = error_comment, has_accept_as_written = has_accept_as_written, hyphen_to_dash = hyphen_to_dash, in_array = in_array, is_set = is_set, is_wikilink = is_wikilink, make_sep_list = make_sep_list, make_wikilink = make_wikilink, remove_wiki_link = remove_wiki_link, safe_for_italics = safe_for_italics, select_one = select_one, set_message = set_message, set_selected_modules = set_selected_modules, strip_apostrophe_markup = strip_apostrophe_markup, substitute = substitute, wrap_style = wrap_style, z = z, -- exported table } b006801b48981b2987f20fc09cbe0dfda525e044 Module:Citation/CS1/Date validation 828 54 124 123 2022-09-04T15:24:36Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local add_prop_cat, is_set, in_array, set_message, substitute, wrap_style; -- imported functions from selected Module:Citation/CS1/Utilities local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration --[[--------------------------< F I L E - S C O P E D E C L A R A T I O N S >-------------------------------- File-scope variables are declared here ]] local lang_object = mw.getContentLanguage(); -- used by is_valid_accessdate(), is_valid_year(), date_name_xlate(); TODO: move to ~/Configuration? local year_limit; -- used by is_valid_year() --[=[-------------------------< I S _ V A L I D _ A C C E S S D A T E >---------------------------------------- returns true if: Wikipedia start date <= accessdate < today + 2 days Wikipedia start date is 2001-01-15T00:00:00 UTC which is 979516800 seconds after 1970-01-01T00:00:00 UTC (the start of Unix time) accessdate is the date provided in |access-date= at time 00:00:00 UTC today is the current date at time 00:00:00 UTC plus 48 hours if today is 2015-01-01T00:00:00 then adding 24 hours gives 2015-01-02T00:00:00 – one second more than today adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow This function does not work if it is fed month names for languages other than English. Wikimedia #time: parser apparently doesn't understand non-English date month names. This function will always return false when the date contains a non-English month name because good1 is false after the call to lang.formatDate(). To get around that call this function with YYYY-MM-DD format dates. ]=] local function is_valid_accessdate (accessdate) local good1, good2; local access_ts, tomorrow_ts; -- to hold Unix time stamps representing the dates good1, access_ts = pcall (lang_object.formatDate, lang_object, 'U', accessdate ); -- convert accessdate value to Unix timestamp good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow if good1 and good2 then -- lang.formatDate() returns a timestamp in the local script which which tonumber() may not understand access_ts = tonumber (access_ts) or lang_object:parseFormattedNumber (access_ts); -- convert to numbers for the comparison; tomorrow_ts = tonumber (tomorrow_ts) or lang_object:parseFormattedNumber (tomorrow_ts); else return false; -- one or both failed to convert to Unix time stamp end if 979516800 <= access_ts and access_ts < tomorrow_ts then -- Wikipedia start date <= accessdate < tomorrow's date return true; else return false; -- accessdate out of range end end --[[--------------------------< G E T _ M O N T H _ N U M B E R >---------------------------------------------- returns a number according to the month in a date: 1 for January, etc. Capitalization and spelling must be correct. If not a valid month, returns 0 ]] local function get_month_number (month) return cfg.date_names['local'].long[month] or cfg.date_names['local'].short[month] or -- look for local names first cfg.date_names['en'].long[month] or cfg.date_names['en'].short[month] or -- failing that, look for English names 0; -- not a recognized month name end --[[--------------------------< G E T _ S E A S O N _ N U M B E R >-------------------------------------------- returns a number according to the sequence of seasons in a year: 21 for Spring, etc. Capitalization and spelling must be correct. If not a valid season, returns 0. 21-24 = Spring, Summer, Autumn, Winter, independent of “Hemisphere” returns 0 when <param> is not |date= Season numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/) which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using numbers 21-41. cs1|2 only supports generic seasons. EDTF does support the distinction between north and south hemisphere seasons but cs1|2 has no way to make that distinction. These additional divisions not currently supported: 25-28 = Spring - Northern Hemisphere, Summer- Northern Hemisphere, Autumn - Northern Hemisphere, Winter - Northern Hemisphere 29-32 = Spring – Southern Hemisphere, Summer– Southern Hemisphere, Autumn – Southern Hemisphere, Winter - Southern Hemisphere 33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each) 37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each) 40-41 = Semestral 1, Semestral-2 (6 months each) ]] local function get_season_number (season, param) if 'date' ~= param then return 0; -- season dates only supported by |date= end return cfg.date_names['local'].season[season] or -- look for local names first cfg.date_names['en'].season[season] or -- failing that, look for English names 0; -- not a recognized season name end --[[--------------------------< G E T _ Q U A R T E R _ N U M B E R >------------------------------------------ returns a number according to the sequence of quarters in a year: 33 for first quarter, etc. Capitalization and spelling must be correct. If not a valid quarter, returns 0. 33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each) returns 0 when <param> is not |date= Quarter numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/) which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using numbers 21-41. cs1|2 only supports generic seasons and quarters. These additional divisions not currently supported: 37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each) 40-41 = Semestral 1, Semestral-2 (6 months each) ]] local function get_quarter_number (quarter, param) if 'date' ~= param then return 0; -- quarter dates only supported by |date= end quarter = mw.ustring.gsub (quarter, ' +', ' '); -- special case replace multiple space chars with a single space char return cfg.date_names['local'].quarter[quarter] or -- look for local names first cfg.date_names['en'].quarter[quarter] or -- failing that, look for English names 0; -- not a recognized quarter name end --[[--------------------------< G E T _ P R O P E R _ N A M E _ N U M B E R >---------------------------------- returns a non-zero number if date contains a recognized proper-name. Capitalization and spelling must be correct. returns 0 when <param> is not |date= ]] local function get_proper_name_number (name, param) if 'date' ~= param then return 0; -- proper-name dates only supported by |date= end return cfg.date_names['local'].named[name] or -- look for local names dates first cfg.date_names['en'].named[name] or -- failing that, look for English names 0; -- not a recognized named date end --[[--------------------------< G E T _ E L E M E N T _ N U M B E R <------------------------------------------ returns true if month or season or quarter or proper name is valid (properly spelled, capitalized, abbreviated) ]] local function get_element_number (element, param) local num; local funcs = {get_month_number, get_season_number, get_quarter_number, get_proper_name_number}; -- list of functions to execute in order for _, func in ipairs (funcs) do -- spin through the function list num = func (element, param); -- call the function and get the returned number if 0 ~= num then -- non-zero when valid month season quarter return num; -- return that number end end return nil; -- not valid end --[[--------------------------< I S _ V A L I D _ Y E A R >---------------------------------------------------- Function gets current year from the server and compares it to year from a citation parameter. Years more than one year in the future are not acceptable. Special case for |pmc-embargo-date=: years more than two years in the future are not acceptable ]] local function is_valid_year (year, param) if not is_set (year_limit) then year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once end year = tonumber (year) or lang_object:parseFormattedNumber (year); -- convert to number for the comparison; if 'pmc-embargo-date' == param then -- special case for |pmc-embargo-date= return year and (year <= tonumber(os.date("%Y"))+2) or false; -- years more than two years in the future are not accepted end return year and (year <= year_limit) or false; end --[[--------------------------< I S _ V A L I D _ D A T E >---------------------------------------------------- Returns true if day is less than or equal to the number of days in month and year is no farther into the future than next year; else returns false. Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately 1923) dates are assumed to be Gregorian. ]] local function is_valid_date (year, month, day, param) local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; local month_length; if not is_valid_year (year, param) then -- no farther into the future than next year except |pmc-embargo-date= no more than two years in the future return false; end month = tonumber (month); -- required for YYYY-MM-DD dates if (2 == month) then -- if February month_length = 28; -- then 28 days unless if 1582 > tonumber(year) then -- Julian calendar if 0 == (year%4) then -- is a leap year? month_length = 29; -- if leap year then 29 days in February end else -- Gregorian calendar if (0 == (year%4) and (0 ~= (year%100) or 0 == (year%400))) then -- is a leap year? month_length = 29; -- if leap year then 29 days in February end end else month_length = days_in_month[month]; end if tonumber (day) > month_length then return false; end return true; end --[[--------------------------< I S _ V A L I D _ M O N T H _ R A N G E _ S T Y L E >-------------------------- Months in a range are expected to have the same style: Jan–Mar or October–December but not February–Mar or Jul–August. This function looks in cfg.date_names{} to see if both month names are listed in the long subtable or both are listed in the short subtable. When both have the same style (both are listed in the same table), returns true; false else ]] local function is_valid_month_range_style (month1, month2) if (cfg.date_names.en.long[month1] and cfg.date_names.en.long[month2]) or -- are both English names listed in the long subtable? (cfg.date_names.en.short[month1] and cfg.date_names.en.short[month2]) or -- are both English names listed in the short subtable? (cfg.date_names['local'].long[month1] and cfg.date_names['local'].long[month2]) or -- are both local names listed in the long subtable? (cfg.date_names['local'].short[month1] and cfg.date_names['local'].short[month2]) then -- are both local names listed in the short subtable? return true; end return false; -- names are mixed end --[[--------------------------< I S _ V A L I D _ M O N T H _ S E A S O N _ R A N G E >------------------------ Check a pair of months or seasons to see if both are valid members of a month or season pair. Month pairs are expected to be left to right, earliest to latest in time. All season ranges are accepted as valid because there are publishers out there who have published a Summer–Spring YYYY issue, hence treat as ok ]] local function is_valid_month_season_range(range_start, range_end, param) local range_start_number = get_month_number (range_start); local range_end_number; if 0 == range_start_number then -- is this a month range? range_start_number = get_season_number (range_start, param); -- not a month; is it a season? get start season number range_end_number = get_season_number (range_end, param); -- get end season number if (0 ~= range_start_number) and (0 ~= range_end_number) and (range_start_number ~= range_end_number) then return true; -- any season pairing is accepted except when both are the same end return false; -- range_start and/or range_end is not a season end -- here when range_start is a month range_end_number = get_month_number (range_end); -- get end month number if range_start_number < range_end_number and -- range_start is a month; does range_start precede range_end? is_valid_month_range_style (range_start, range_end) then -- do months have the same style? return true; -- proper order and same style end return false; -- range_start month number is greater than or equal to range end number; or range end isn't a month end --[[--------------------------< M A K E _ C O I N S _ D A T E >------------------------------------------------ This function receives a table of date parts for one or two dates and an empty table reference declared in Module:Citation/CS1. The function is called only for |date= parameters and only if the |date=<value> is determined to be a valid date format. The question of what to do with invalid date formats is not answered here. The date parts in the input table are converted to an ISO 8601 conforming date string: single whole dates: yyyy-mm-dd month and year dates: yyyy-mm year dates: yyyy ranges: yyyy-mm-dd/yyyy-mm-dd yyyy-mm/yyyy-mm yyyy/yyyy Dates in the Julian calendar are reduced to year or year/year so that we don't have to do calendar conversion from Julian to Proleptic Gregorian. The input table has: year, year2 – always present; if before 1582, ignore months and days if present month, month2 – 0 if not provided, 1-12 for months, 21-24 for seasons; 99 Christmas day, day2 – 0 if not provided, 1-31 for days the output table receives: rftdate: an ISO 8601 formatted date rftchron: a free-form version of the date, usually without year which is in rftdate (season ranges and proper-name dates) rftssn: one of four season keywords: winter, spring, summer, fall (lowercase) rftquarter: one of four values: 1, 2, 3, 4 ]] local function make_COinS_date (input, tCOinS_date) local date; -- one date or first date in a range local date2 = ''; -- end of range date -- start temporary Julian / Gregorian calendar uncertainty detection local year = tonumber(input.year); -- this temporary code to determine the extent of sources dated to the Julian/Gregorian local month = tonumber(input.month); -- interstice 1 October 1582 – 1 January 1926 local day = tonumber (input.day); if (0 ~= day) and -- day must have a value for this to be a whole date (((1582 == year) and (10 <= month) and (12 >= month)) or -- any whole 1582 date from 1 October to 31 December or ((1926 == year) and (1 == month) and (1 == input.day)) or -- 1 January 1926 or ((1582 < year) and (1925 >= year))) then -- any date 1 January 1583 – 31 December 1925 tCOinS_date.inter_cal_cat = true; -- set category flag true end -- end temporary Julian / Gregorian calendar uncertainty detection if 1582 > tonumber(input.year) or 20 < tonumber(input.month) then -- Julian calendar or season so &rft.date gets year only date = input.year; if 0 ~= input.year2 and input.year ~= input.year2 then -- if a range, only the second year portion when not the same as range start year date = string.format ('%.4d/%.4d', tonumber(input.year), tonumber(input.year2)) -- assemble the date range end if 20 < tonumber(input.month) then -- if season or proper-name date local season = {[24] = 'winter', [21] = 'spring', [22] = 'summer', [23] = 'fall', [33] = '1', [34] = '2', [35] = '3', [36] = '4', [98] = 'Easter', [99] = 'Christmas'}; -- seasons lowercase, no autumn; proper-names use title case if 0 == input.month2 then -- single season date if 40 < tonumber(input.month) then tCOinS_date.rftchron = season[input.month]; -- proper-name dates elseif 30 < tonumber(input.month) then tCOinS_date.rftquarter = season[input.month]; -- quarters else tCOinS_date.rftssn = season[input.month]; -- seasons end else -- season range with a second season specified if input.year ~= input.year2 then -- season year – season year range or season year–year tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this? if 0~= input.month2 then tCOinS_date.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2); end else -- season–season year range tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this? tCOinS_date.rftchron = season[input.month] .. '–' .. season[input.month2]; -- season–season year range end end end tCOinS_date.rftdate = date; return; -- done end if 0 ~= input.day then date = string.format ('%s-%.2d-%.2d', input.year, tonumber(input.month), tonumber(input.day)); -- whole date elseif 0 ~= input.month then date = string.format ('%s-%.2d', input.year, tonumber(input.month)); -- year and month else date = string.format ('%s', input.year); -- just year end if 0 ~= input.year2 then if 0 ~= input.day2 then date2 = string.format ('/%s-%.2d-%.2d', input.year2, tonumber(input.month2), tonumber(input.day2)); -- whole date elseif 0 ~= input.month2 then date2 = string.format ('/%s-%.2d', input.year2, tonumber(input.month2)); -- year and month else date2 = string.format ('/%s', input.year2); -- just year end end tCOinS_date.rftdate = date .. date2; -- date2 has the '/' separator return; end --[[--------------------------< P A T T E R N S >-------------------------------------------------------------- this is the list of patterns for date formats that this module recognizes. Approximately the first half of these patterns represent formats that might be reformatted into another format. Those that might be reformatted have 'indicator' letters that identify the content of the matching capture: 'd' (day), 'm' (month), 'a' (anchor year), 'y' (year); second day, month, year have a '2' suffix. These patterns are used for both date validation and for reformatting. This table should not be moved to ~/Configuration because changes to this table require changes to check_date() and to reformatter() and reformat_date() ]] local patterns = { -- year-initial numerical year-month-day ['ymd'] = {'^(%d%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'}, -- month-initial: month day, year ['Mdy'] = {'^(%D-) +([1-9]%d?), +((%d%d%d%d?)%a?)$', 'm', 'd', 'a', 'y'}, -- month-initial day range: month day–day, year; days are separated by endash ['Md-dy'] = {'^(%D-) +([1-9]%d?)[%-–]([1-9]%d?), +((%d%d%d%d)%a?)$', 'm', 'd', 'd2', 'a', 'y'}, -- day-initial: day month year ['dMy'] = {'^([1-9]%d?) +(%D-) +((%d%d%d%d?)%a?)$', 'd', 'm', 'a', 'y'}, -- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed; not supported at en.wiki -- ['yMd'] = {'^((%d%d%d%d?)%a?) +(%D-) +(%d%d?)$', 'a', 'y', 'm', 'd'}, -- day-range-initial: day–day month year; days are separated by endash ['d-dMy'] = {'^([1-9]%d?)[%-–]([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'd2', 'm', 'a', 'y'}, -- day initial month-day-range: day month - day month year; uses spaced endash ['dM-dMy'] = {'^([1-9]%d?) +(%D-) +[%-–] +([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'm', 'd2', 'm2', 'a', 'y'}, -- month initial month-day-range: month day – month day, year; uses spaced endash ['Md-Mdy'] = {'^(%D-) +([1-9]%d?) +[%-–] +(%D-) +([1-9]%d?), +((%d%d%d%d)%a?)$','m', 'd', 'm2', 'd2', 'a', 'y'}, -- day initial month-day-year-range: day month year - day month year; uses spaced endash ['dMy-dMy'] = {'^([1-9]%d?) +(%D-) +(%d%d%d%d) +[%-–] +([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'm', 'y', 'd2', 'm2', 'a', 'y2'}, -- month initial month-day-year-range: month day, year – month day, year; uses spaced endash ['Mdy-Mdy'] = {'^(%D-) +([1-9]%d?), +(%d%d%d%d) +[%-–] +(%D-) +([1-9]%d?), +((%d%d%d%d)%a?)$', 'm', 'd', 'y', 'm2', 'd2', 'a', 'y2'}, -- these date formats cannot be converted, per se, but month name can be rendered short or long -- month/season year - month/season year; separated by spaced endash ['My-My'] = {'^(%D-) +(%d%d%d%d) +[%-–] +(%D-) +((%d%d%d%d)%a?)$', 'm', 'y', 'm2', 'a', 'y2'}, -- month/season range year; months separated by endash ['M-My'] = {'^(%D-)[%-–](%D-) +((%d%d%d%d)%a?)$', 'm', 'm2', 'a', 'y'}, -- month/season year or proper-name year; quarter year when First Quarter YYYY etc. ['My'] = {'^([^%d–]-) +((%d%d%d%d)%a?)$', 'm', 'a', 'y'}, -- this way because endash is a member of %D; %D- will match January–March 2019 when it shouldn't -- these date formats cannot be converted ['Sy4-y2'] = {'^(%D-) +((%d%d)%d%d)[%-–]((%d%d)%a?)$'}, -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash ['Sy-y'] = {'^(%D-) +(%d%d%d%d)[%-–]((%d%d%d%d)%a?)$'}, -- special case Winter/Summer year-year; year separated with unspaced endash ['y-y'] = {'^(%d%d%d%d?)[%-–]((%d%d%d%d?)%a?)$'}, -- year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999 ['y4-y2'] = {'^((%d%d)%d%d)[%-–]((%d%d)%a?)$'}, -- year range: YYYY–YY; separated by unspaced endash ['y'] = {'^((%d%d%d%d?)%a?)$'}, -- year; here accept either YYY or YYYY } --[[--------------------------< I S _ V A L I D _ E M B A R G O _ D A T E >------------------------------------ returns true and date value if that value has proper dmy, mdy, ymd format. returns false and 9999 (embargoed forever) when date value is not proper format; assumes that when |pmc-embargo-date= is set, the editor intended to embargo a PMC but |pmc-embargo-date= does not hold a single date. ]] local function is_valid_embargo_date (v) if v:match (patterns['ymd'][1]) or -- ymd v:match (patterns['Mdy'][1]) or -- dmy v:match (patterns['dMy'][1]) then -- mdy return true, v; end return false, '9999'; -- if here not good date so return false and set embargo date to long time in future end --[[--------------------------< C H E C K _ D A T E >---------------------------------------------------------- Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only allowed range separator is endash. Additionally, check the date to see that it is a real date: no 31 in 30-day months; no 29 February when not a leap year. Months, both long-form and three character abbreviations, and seasons must be spelled correctly. Future years beyond next year are not allowed. If the date fails the format tests, this function returns false and does not return values for anchor_year and COinS_date. When this happens, the date parameter is (DEBUG: not?) used in the COinS metadata and the CITEREF identifier gets its year from the year parameter if present otherwise CITEREF does not get a date value. Inputs: date_string - date string from date-holding parameters (date, year, publication-date, access-date, pmc-embargo-date, archive-date, lay-date) Returns: false if date string is not a real date; else true, anchor_year, COinS_date anchor_year can be used in CITEREF anchors COinS_date is ISO 8601 format date; see make_COInS_date() ]] local function check_date (date_string, param, tCOinS_date) local year; -- assume that year2, months, and days are not used; local year2 = 0; -- second year in a year range local month = 0; local month2 = 0; -- second month in a month range local day = 0; local day2 = 0; -- second day in a day range local anchor_year; local coins_date; if date_string:match (patterns['ymd'][1]) then -- year-initial numerical year month day format year, month, day = date_string:match (patterns['ymd'][1]); if 12 < tonumber(month) or 1 > tonumber(month) or 1582 > tonumber(year) or 0 == tonumber(day) then return false; end -- month or day number not valid or not Gregorian calendar anchor_year = year; elseif mw.ustring.match(date_string, patterns['Mdy'][1]) then -- month-initial: month day, year month, day, anchor_year, year = mw.ustring.match(date_string, patterns['Mdy'][1]); month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months elseif mw.ustring.match(date_string, patterns['Md-dy'][1]) then -- month-initial day range: month day–day, year; days are separated by endash month, day, day2, anchor_year, year = mw.ustring.match(date_string, patterns['Md-dy'][1]); if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same; month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months month2=month; -- for metadata year2 = year; elseif mw.ustring.match(date_string, patterns['dMy'][1]) then -- day-initial: day month year day, month, anchor_year, year = mw.ustring.match(date_string, patterns['dMy'][1]); month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months --[[ NOT supported at en.wiki elseif mw.ustring.match(date_string, patterns['yMd'][1]) then -- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed anchor_year, year, month, day = mw.ustring.match(date_string, patterns['yMd'][1]); month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months -- end NOT supported at en.wiki ]] elseif mw.ustring.match(date_string, patterns['d-dMy'][1]) then -- day-range-initial: day–day month year; days are separated by endash day, day2, month, anchor_year, year = mw.ustring.match(date_string, patterns['d-dMy'][1]); if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same; month = get_month_number (month); if 0 == month then return false; end -- return false if month text isn't one of the twelve months month2 = month; -- for metadata year2 = year; elseif mw.ustring.match(date_string, patterns['dM-dMy'][1]) then -- day initial month-day-range: day month - day month year; uses spaced endash day, month, day2, month2, anchor_year, year = mw.ustring.match(date_string, patterns['dM-dMy'][1]); if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end -- date range order is left to right: earlier to later; month = get_month_number (month); -- for metadata month2 = get_month_number (month2); year2 = year; elseif mw.ustring.match(date_string, patterns['Md-Mdy'][1]) then -- month initial month-day-range: month day – month day, year; uses spaced endash month, day, month2, day2, anchor_year, year = mw.ustring.match(date_string, patterns['Md-Mdy'][1]); if (not is_valid_month_season_range(month, month2, param)) or not is_valid_year(year) then return false; end month = get_month_number (month); -- for metadata month2 = get_month_number (month2); year2 = year; elseif mw.ustring.match(date_string, patterns['dMy-dMy'][1]) then -- day initial month-day-year-range: day month year - day month year; uses spaced endash day, month, year, day2, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns['dMy-dMy'][1]); if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style month = get_month_number (month); -- for metadata month2 = get_month_number (month2); if 0 == month or 0 == month2 then return false; end -- both must be valid elseif mw.ustring.match(date_string, patterns['Mdy-Mdy'][1]) then -- month initial month-day-year-range: month day, year – month day, year; uses spaced endash month, day, year, month2, day2, anchor_year, year2 = mw.ustring.match(date_string, patterns['Mdy-Mdy'][1]); if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style month = get_month_number (month); -- for metadata month2 = get_month_number(month2); if 0 == month or 0 == month2 then return false; end -- both must be valid elseif mw.ustring.match(date_string, patterns['Sy4-y2'][1]) then -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash local century; month, year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns['Sy4-y2'][1]); if 'Winter' ~= month and 'Summer' ~= month then return false end; -- 'month' can only be Winter or Summer anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years year2 = century..year2; -- add the century to year2 for comparisons if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later if not is_valid_year(year2) then return false; end -- no year farther in the future than next year month = get_season_number(month, param); elseif mw.ustring.match(date_string, patterns['Sy-y'][1]) then -- special case Winter/Summer year-year; year separated with unspaced endash month, year, anchor_year, year2 = mw.ustring.match(date_string, patterns['Sy-y'][1]); month = get_season_number (month, param); -- <month> can only be winter or summer; also for metadata if (month ~= cfg.date_names['en'].season['Winter']) and (month ~= cfg.date_names['en'].season['Summer']) then return false; -- not Summer or Winter; abandon end anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later if not is_valid_year(year2) then return false; end -- no year farther in the future than next year elseif mw.ustring.match(date_string, patterns['My-My'][1]) then -- month/season year - month/season year; separated by spaced endash month, year, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns['My-My'][1]); anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same if not is_valid_year(year2) then return false; end -- no year farther in the future than next year if 0 ~= get_month_number(month) and 0 ~= get_month_number(month2) and is_valid_month_range_style(month, month2) then -- both must be month year, same month style month = get_month_number(month); month2 = get_month_number(month2); elseif 0 ~= get_season_number(month, param) and 0 ~= get_season_number(month2, param) then -- both must be season year, not mixed month = get_season_number(month, param); month2 = get_season_number(month2, param); else return false; end elseif mw.ustring.match(date_string, patterns['M-My'][1]) then -- month/season range year; months separated by endash month, month2, anchor_year, year = mw.ustring.match(date_string, patterns['M-My'][1]); if (not is_valid_month_season_range(month, month2, param)) or (not is_valid_year(year)) then return false; end if 0 ~= get_month_number(month) then -- determined to be a valid range so just check this one to know if month or season month = get_month_number(month); month2 = get_month_number(month2); if 0 == month or 0 == month2 then return false; end else month = get_season_number(month, param); month2 = get_season_number(month2, param); end year2 = year; elseif mw.ustring.match(date_string, patterns['My'][1]) then -- month/season/quarter/proper-name year month, anchor_year, year = mw.ustring.match(date_string, patterns['My'][1]); if not is_valid_year(year) then return false; end month = get_element_number(month, param); -- get month season quarter proper-name number or nil if not month then return false; end -- not valid whatever it is elseif mw.ustring.match(date_string, patterns['y-y'][1]) then -- Year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999 year, anchor_year, year2 = mw.ustring.match(date_string, patterns['y-y'][1]); anchor_year = year .. '–' .. anchor_year; -- assemble anchor year from both years if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same if not is_valid_year(year2) then return false; end -- no year farther in the future than next year elseif mw.ustring.match(date_string, patterns['y4-y2'][1]) then -- Year range: YYYY–YY; separated by unspaced endash local century; year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns['y4-y2'][1]); anchor_year = year .. '–' .. anchor_year; -- assemble anchor year from both years if in_array (param, {'date', 'publication-date', 'year'}) then add_prop_cat ('year-range-abbreviated'); end if 13 > tonumber(year2) then return false; end -- don't allow 2003-05 which might be May 2003 year2 = century .. year2; -- add the century to year2 for comparisons if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same if not is_valid_year(year2) then return false; end -- no year farther in the future than next year elseif mw.ustring.match(date_string, patterns['y'][1]) then -- year; here accept either YYY or YYYY anchor_year, year = mw.ustring.match(date_string, patterns['y'][1]); if false == is_valid_year(year) then return false; end else return false; -- date format not one of the MOS:DATE approved formats end if 'access-date' == param then -- test accessdate here because we have numerical date parts if 0 ~= year and 0 ~= month and 0 ~= day and -- all parts of a single date required 0 == year2 and 0 == month2 and 0 == day2 then -- none of these; accessdate must not be a range if not is_valid_accessdate(year .. '-' .. month .. '-' .. day) then return false; -- return false when accessdate out of bounds end else return false; -- return false when accessdate is a range of two dates end end local result=true; -- check whole dates for validity; assume true because not all dates will go through this test if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then -- YMD (simple whole date) result = is_valid_date (year, month, day, param); -- <param> for |pmc-embargo-date= elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 ~= day2 then -- YMD-d (day range) result = is_valid_date (year, month, day); result = result and is_valid_date (year, month, day2); elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-md (day month range) result = is_valid_date (year, month, day); result = result and is_valid_date (year, month2, day2); elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 ~= year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-ymd (day month year range) result = is_valid_date(year, month, day); result = result and is_valid_date(year2, month2, day2); end if false == result then return false; end if nil ~= tCOinS_date then -- this table only passed into this function when testing |date= parameter values make_COinS_date ({year = year, month = month, day = day, year2 = year2, month2 = month2, day2 = day2}, tCOinS_date); -- make an ISO 8601 date string for COinS end return true, anchor_year; -- format is good and date string represents a real date end --[[--------------------------< D A T E S >-------------------------------------------------------------------- Cycle the date-holding parameters in passed table date_parameters_list through check_date() to check compliance with MOS:DATE. For all valid dates, check_date() returns true. The |date= parameter test is unique, it is the only date holding parameter from which values for anchor_year (used in CITEREF identifiers) and COinS_date (used in the COinS metadata) are derived. The |date= parameter is the only date-holding parameter that is allowed to contain the no-date keywords "n.d." or "nd" (without quotes). Unlike most error messages created in this module, only one error message is created by this function. Because all of the date holding parameters are processed serially, parameters with errors are added to the <error_list> sequence table as the dates are tested. ]] local function dates(date_parameters_list, tCOinS_date, error_list) local anchor_year; -- will return as nil if the date being tested is not |date= local COinS_date; -- will return as nil if the date being tested is not |date= local embargo_date; -- if embargo date is a good dmy, mdy, ymd date then holds original value else reset to 9999 local good_date = false; for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list if is_set(v.val) then -- if the parameter has a value v.val = mw.ustring.gsub(v.val, '%d', cfg.date_names.local_digits); -- translate 'local' digits to Western 0-9 if v.val:match("^c%. [1-9]%d%d%d?%a?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year= local year = v.val:match("c%. ([1-9]%d%d%d?)%a?"); -- get the year portion so it can be tested if 'date' == k then anchor_year, COinS_date = v.val:match("((c%. [1-9]%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter good_date = is_valid_year(year); elseif 'year' == k then good_date = is_valid_year(year); end elseif 'date' == k then -- if the parameter is |date= if v.val:match("^n%.d%.%a?$") then -- ToDo: I18N -- if |date=n.d. with or without a CITEREF disambiguator good_date, anchor_year, COinS_date = true, v.val:match("((n%.d%.)%a?)"); -- ToDo: I18N -- "n.d."; no error when date parameter is set to no date elseif v.val:match("^nd%a?$") then -- ToDo: I18N -- if |date=nd with or without a CITEREF disambiguator good_date, anchor_year, COinS_date = true, v.val:match("((nd)%a?)"); -- ToDo: I18N -- "nd"; no error when date parameter is set to no date else good_date, anchor_year, COinS_date = check_date (v.val, k, tCOinS_date); -- go test the date end elseif 'year' == k then -- if the parameter is |year= it should hold only a year value if v.val:match("^[1-9]%d%d%d?%a?$") then -- if |year = 3 or 4 digits only with or without a CITEREF disambiguator good_date, anchor_year, COinS_date = true, v.val:match("((%d+)%a?)"); end elseif 'pmc-embargo-date' == k then -- if the parameter is |pmc-embargo-date= good_date = check_date (v.val, k); -- go test the date if true == good_date then -- if the date is a valid date good_date, embargo_date = is_valid_embargo_date (v.val); -- is |pmc-embargo-date= date a single dmy, mdy, or ymd formatted date? yes: returns embargo date; no: returns 9999 end else -- any other date-holding parameter good_date = check_date (v.val, k); -- go test the date end if false == good_date then -- assemble one error message so we don't add the tracking category multiple times table.insert (error_list, wrap_style ('parameter', v.name)); -- make parameter name suitable for error message list end end end return anchor_year, embargo_date; -- and done end --[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------ Compare the value provided in |year= with the year value(s) provided in |date=. This function sets a local numeric value: 0 - year value does not match the year value in date 1 - (default) year value matches the year value in date or one of the year values when date contains two years 2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx) the numeric value in <result> determines the 'output' if any from this function: 0 – adds error message to error_list sequence table 1 – adds maint cat 2 – does nothing ]] local function year_date_check (year_string, year_origin, date_string, date_origin, error_list) local year; local date1; local date2; local result = 1; -- result of the test; assume that the test passes year = year_string:match ('(%d%d%d%d?)'); if date_string:match ('%d%d%d%d%-%d%d%-%d%d') and year_string:match ('%d%d%d%d%a') then --special case where both date and year are required YYYY-MM-DD and YYYYx date1 = date_string:match ('(%d%d%d%d)'); year = year_string:match ('(%d%d%d%d)'); if year ~= date1 then result = 0; -- years don't match else result = 2; -- years match; but because disambiguated, don't add to maint cat end elseif date_string:match ("%d%d%d%d?.-%d%d%d%d?") then -- any of the standard range formats of date with two three- or four-digit years date1, date2 = date_string:match ("(%d%d%d%d?).-(%d%d%d%d?)"); if year ~= date1 and year ~= date2 then result = 0; end elseif mw.ustring.match(date_string, "%d%d%d%d[%-–]%d%d") then -- YYYY-YY date ranges local century; date1, century, date2 = mw.ustring.match(date_string, "((%d%d)%d%d)[%-–]+(%d%d)"); date2 = century..date2; -- convert YY to YYYY if year ~= date1 and year ~= date2 then result = 0; end elseif date_string:match ("%d%d%d%d?") then -- any of the standard formats of date with one year date1 = date_string:match ("(%d%d%d%d?)"); if year ~= date1 then result = 0; end else -- should never get here; this function called only when no other date errors result = 0; -- no recognizable year in date end if 0 == result then -- year / date mismatch table.insert (error_list, substitute (cfg.messages['mismatch'], {year_origin, date_origin})); -- add error message to error_list sequence table elseif 1 == result then -- redundant year / date set_message ('maint_date_year'); -- add a maint cat end end --[[--------------------------< R E F O R M A T T E R >-------------------------------------------------------- reformat 'date' into new format specified by format_param if pattern_idx (the current format of 'date') can be reformatted. Does the grunt work for reformat_dates(). The table re_formats maps pattern_idx (current format) and format_param (desired format) to a table that holds: format string used by string.format() identifier letters ('d', 'm', 'y', 'd2', 'm2', 'y2') that serve as indexes into a table t{} that holds captures from mw.ustring.match() for the various date parts specified by patterns[pattern_idx][1] Items in patterns{} have the general form: ['ymd'] = {'^(%d%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'}, where: ['ymd'] is pattern_idx patterns['ymd'][1] is the match pattern with captures for mw.ustring.match() patterns['ymd'][2] is an indicator letter identifying the content of the first capture patterns['ymd'][3] ... the second capture etc. when a pattern matches a date, the captures are loaded into table t{} in capture order using the idemtifier characters as indexes into t{} For the above, a ymd date is in t{} as: t.y = first capture (year), t.m = second capture (month), t.d = third capture (day) To reformat, this function is called with the pattern_idx that matches the current format of the date and with format_param set to the desired format. This function loads table t{} as described and then calls string.format() with the format string specified by re_format[pattern_idx][format_param][1] using values taken from t{} according to the capture identifier letters specified by patterns[pattern_idx][format_param][n] where n is 2.. ]] local re_formats = { ['ymd'] = { -- date format is ymd; reformat to: ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy -- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki }, ['Mdy'] = { -- date format is Mdy; reformat to: ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- for long/short reformatting ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy ['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd -- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki }, ['dMy'] = { -- date format is dMy; reformat to: ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- for long/short reformatting ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy ['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd -- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki }, ['Md-dy'] = { -- date format is Md-dy; reformat to: ['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'}, -- for long/short reformatting ['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'}, -- |df=dmy -> d-dMy }, ['d-dMy'] = { -- date format is d-d>y; reformat to: ['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'}, -- for long/short reformatting ['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'}, -- |df=mdy -> Md-dy }, ['dM-dMy'] = { -- date format is dM-dMy; reformat to: ['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'}, -- for long/short reformatting ['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'}, -- |df=mdy -> Md-Mdy }, ['Md-Mdy'] = { -- date format is Md-Mdy; reformat to: ['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'}, -- for long/short reformatting ['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'}, -- |df=dmy -> dM-dMy }, ['dMy-dMy'] = { -- date format is dMy-dMy; reformat to: ['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'}, -- for long/short reformatting ['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'}, -- |df=mdy -> Mdy-Mdy }, ['Mdy-Mdy'] = { -- date format is Mdy-Mdy; reformat to: ['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'}, -- for long/short reformatting ['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'}, -- |df=dmy -> dMy-dMy }, ['My-My'] = { -- these for long/short reformatting ['any'] = {'%s %s – %s %s', 'm', 'y', 'm2', 'y2'}, -- dmy/mdy agnostic }, ['M-My'] = { -- these for long/short reformatting ['any'] = {'%s–%s %s', 'm', 'm2', 'y'}, -- dmy/mdy agnostic }, ['My'] = { -- these for long/short reformatting ['any'] = {'%s %s', 'm', 'y'}, -- dmy/mdy agnostic }, -- ['yMd'] = { -- not supported at en.wiki -- ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy -- ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy -- ['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd -- }, } local function reformatter (date, pattern_idx, format_param, mon_len) if not in_array (pattern_idx, {'ymd', 'Mdy', 'Md-dy', 'dMy', 'yMd', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) then return; -- not in this set of date format patterns then not a reformattable date end if 'ymd' == format_param and in_array (pattern_idx, {'ymd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) then return; -- ymd date ranges not supported at en.wiki; no point in reformatting ymd to ymd end if in_array (pattern_idx, {'My', 'M-My', 'My-My'}) then -- these are not dmy/mdy so can't be 'reformatted' into either format_param = 'any'; -- so format-agnostic end -- yMd is not supported at en.wiki; when yMd is supported at your wiki, uncomment the next line -- if 'yMd' == format_param and in_array (pattern_idx, {'yMd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy'}) then -- these formats not convertable; yMd not supported at en.wiki if 'yMd' == format_param then -- yMd not supported at en.wiki; when yMd is supported at your wiki, remove or comment-out this line return; -- not a reformattable date end local c1, c2, c3, c4, c5, c6, c7; -- these hold the captures specified in patterns[pattern_idx][1] c1, c2, c3, c4, c5, c6, c7 = mw.ustring.match (date, patterns[pattern_idx][1]); -- get the captures local t = { -- table that holds k/v pairs of date parts from the captures and patterns[pattern_idx][2..] [patterns[pattern_idx][2]] = c1; -- at minimum there is always one capture with a matching indicator letter [patterns[pattern_idx][3] or 'x'] = c2; -- patterns can have a variable number of captures; each capture requires an indicator letter; [patterns[pattern_idx][4] or 'x'] = c3; -- where there is no capture, there is no indicator letter so n in patterns[pattern_idx][n] will be nil; [patterns[pattern_idx][5] or 'x'] = c4; -- the 'x' here spoofs an indicator letter to prevent 'table index is nil' error [patterns[pattern_idx][6] or 'x'] = c5; [patterns[pattern_idx][7] or 'x'] = c6; [patterns[pattern_idx][8] or 'x'] = c7; }; if t.a then -- if this date has an anchor year capture (all convertable date formats except ymd) if t.y2 then -- for year range date formats t.y2 = t.a; -- use the anchor year capture when reassembling the date else -- here for single date formats (except ymd) t.y = t.a; -- use the anchor year capture when reassembling the date end end if tonumber(t.m) then -- if raw month is a number (converting from ymd) if 's' == mon_len then -- if we are to use abbreviated month names t.m = cfg.date_names['inv_local_short'][tonumber(t.m)]; -- convert it to a month name else t.m = cfg.date_names['inv_local_long'][tonumber(t.m)]; -- convert it to a month name end t.d = t.d:gsub ('0(%d)', '%1'); -- strip leading '0' from day if present elseif 'ymd' == format_param then -- when converting to ymd t.y = t.y:gsub ('%a', ''); -- strip CITREF disambiguator if present; anchor year already known so process can proceed; TODO: maint message? if 1582 > tonumber (t.y) then -- ymd format dates not allowed before 1582 return; end t.m = string.format ('%02d', get_month_number (t.m)); -- make sure that month and day are two digits t.d = string.format ('%02d', t.d); elseif mon_len then -- if mon_len is set to either 'short' or 'long' for _, mon in ipairs ({'m', 'm2'}) do -- because there can be two month names, check both if t[mon] then t[mon] = get_month_number (t[mon]); -- get the month number for this month (is length agnostic) if 0 == t[mon] then return; end -- seasons and named dates can't be converted t[mon] = (('s' == mon_len) and cfg.date_names['inv_local_short'][t[mon]]) or cfg.date_names['inv_local_long'][t[mon]]; -- fetch month name according to length end end end local new_date = string.format (re_formats[pattern_idx][format_param][1], -- format string t[re_formats[pattern_idx][format_param][2]], -- named captures from t{} t[re_formats[pattern_idx][format_param][3]], t[re_formats[pattern_idx][format_param][4]], t[re_formats[pattern_idx][format_param][5]], t[re_formats[pattern_idx][format_param][6]], t[re_formats[pattern_idx][format_param][7]], t[re_formats[pattern_idx][format_param][8]] ); return new_date; end --[[-------------------------< R E F O R M A T _ D A T E S >-------------------------------------------------- Reformats existing dates into the format specified by format. format is one of several manual keywords: dmy, dmy-all, mdy, mdy-all, ymd, ymd-all. The -all version includes access- and archive-dates; otherwise these dates are not reformatted. This function allows automatic date formatting. In ~/Configuration, the article source is searched for one of the {{use xxx dates}} templates. If found, xxx becomes the global date format as xxx-all. If |cs1-dates= in {{use xxx dates}} has legitimate value then that value determines how cs1|2 dates will be rendered. Legitimate values for |cs1-dates= are: l - all dates are rendered with long month names ls - publication dates use long month names; access-/archive-dates use abbreviated month names ly - publication dates use long month names; access-/archive-dates rendered in ymd format s - all dates are rendered with abbreviated (short) month names sy - publication dates use abbreviated month names; access-/archive-dates rendered in ymd format y - all dates are rendered in ymd format the format argument for automatic date formatting will be the format specified by {{use xxx dates}} with the value supplied by |cs1-dates so one of: xxx-l, xxx-ls, xxx-ly, xxx-s, xxx-sy, xxx-y, or simply xxx (|cs1-dates= empty, omitted, or invalid) where xxx shall be either of dmy or mdy. dates are extracted from date_parameters_list, reformatted (if appropriate), and then written back into the list in the new format. Dates in date_parameters_list are presumed here to be valid (no errors). This function returns true when a date has been reformatted, false else. Actual reformatting is done by reformatter(). ]] local function reformat_dates (date_parameters_list, format) local all = false; -- set to false to skip access- and archive-dates local len_p = 'l'; -- default publication date length shall be long local len_a = 'l'; -- default access-/archive-date length shall be long local result = false; local new_date; if format:match('%a+%-all') then -- manual df keyword; auto df keyword when length not specified in {{use xxx dates}}; format = format:match('(%a+)%-all'); -- extract the format all = true; -- all dates are long format dates because this keyword doesn't specify length elseif format:match('%a+%-[lsy][sy]?') then -- auto df keywords; internal only all = true; -- auto df applies to all dates; use length specified by capture len_p for all dates format, len_p, len_a = format:match('(%a+)%-([lsy])([sy]?)'); -- extract the format and length keywords if 'y' == len_p then -- because allowed by MOS:DATEUNIFY (sort of) range dates and My dates not reformatted format = 'ymd'; -- override {{use xxx dates}} elseif (not is_set(len_a)) or (len_p == len_a) then -- no access-/archive-date length specified or same length as publication dates then len_a = len_p; -- in case len_a not set end end -- else only publication dates and they are long for param_name, param_val in pairs (date_parameters_list) do -- for each date-holding parameter in the list if is_set (param_val.val) then -- if the parameter has a value if not (not all and in_array (param_name, {'access-date', 'archive-date'})) then -- skip access- or archive-date unless format is xxx-all; yeah, ugly; TODO: find a better way for pattern_idx, pattern in pairs (patterns) do if mw.ustring.match (param_val.val, pattern[1]) then if all and in_array (param_name, {'access-date', 'archive-date'}) then -- if this date is an access- or archive-date new_date = reformatter (param_val.val, pattern_idx, (('y' == len_a) and 'ymd') or format, len_a); -- choose ymd or dmy/mdy according to len_a setting else -- all other dates new_date = reformatter (param_val.val, pattern_idx, format, len_p); end if new_date then -- set when date was reformatted date_parameters_list[param_name].val = new_date; -- update date in date list result = true; -- and announce that changes have been made end end -- if end -- for end -- if end -- if end -- for return result; -- declare boolean result and done end --[[--------------------------< D A T E _ H Y P H E N _ T O _ D A S H >---------------------------------------- Loops through the list of date-holding parameters and converts any hyphen to an ndash. Not called if the cs1|2 template has any date errors. Modifies the date_parameters_list and returns true if hyphens are replaced, else returns false. ]] local function date_hyphen_to_dash (date_parameters_list) local result = false; local n; for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list if is_set (param_val.val) and not mw.ustring.match (param_val.val, patterns.ymd[1]) then -- for those that are not ymd dates (ustring because here digits may not be Western) param_val.val, n = param_val.val:gsub ('%-', '–'); -- replace any hyphen with ndash if 0 ~= n then date_parameters_list[param_name].val = param_val.val; -- update the list result = true; end end end return result; -- so we know if any hyphens were replaced end --[[-------------------------< D A T E _ N A M E _ X L A T E >------------------------------------------------ Attempts to translate English date names to local-language date names using names supplied by MediaWiki's date parser function. This is simple name-for-name replacement and may not work for all languages. if xlat_dig is true, this function will also translate Western (English) digits to the local language's digits. This will also translate ymd dates. ]] local function date_name_xlate (date_parameters_list, xlt_dig) local xlate; local mode; -- long or short month names local modified = false; local date; local sources_t = { {cfg.date_names.en.long, cfg.date_names.inv_local_long}, -- for translating long English month names to long local month names {cfg.date_names.en.short, cfg.date_names.inv_local_short}, -- short month names {cfg.date_names.en.quarter, cfg.date_names.inv_local_quarter}, -- quarter date names {cfg.date_names.en.season, cfg.date_names.inv_local_season}, -- season date nam {cfg.date_names.en.named, cfg.date_names.inv_local_named}, -- named dates } local function is_xlateable (month) -- local function to get local date name that replaces existing English-language date name for _, date_names_t in ipairs (sources_t) do -- for each sequence table in date_names_t if date_names_t[1][month] then -- if date name is English month (long or short), quarter, season or named and if date_names_t[2][date_names_t[1][month]] then -- if there is a matching local date name return date_names_t[2][date_names_t[1][month]]; -- return the local date name end end end end for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list if is_set(param_val.val) then -- if the parameter has a value date = param_val.val; for month in mw.ustring.gmatch (date, '[%a ]+') do -- iterate through all date names in the date (single date or date range) month = mw.text.trim (month); -- this because quarterly dates contain whitespace xlate = is_xlateable (month); -- get translate <month>; returns translation or nil -- if cfg.date_names.en.long[month] then -- long month dates -- if cfg.date_names.inv_local_long[cfg.date_names.en.long[month]] then -- xlate = cfg.date_names.inv_local_long[cfg.date_names.en.long[month]]; -- end ---- mode = 'F'; -- English name is long so use long local name -- elseif cfg.date_names.en.short[month] then -- short month dates -- if cfg.date_names.inv_local_short[cfg.date_names.en.short[month]] then -- xlate = cfg.date_names.inv_local_short[cfg.date_names.en.short[month]]; -- end ---- mode = 'M'; -- English name is short so use short local name -- elseif cfg.date_names.en.quarter[month] then -- quarter dates -- if cfg.date_names.inv_local_quarter[cfg.date_names.en.quarter[month]] then -- xlate = cfg.date_names.inv_local_quarter[cfg.date_names.en.quarter[month]]; -- end -- elseif cfg.date_names.en.season[month] then -- season dates -- if cfg.date_names.inv_local_season[cfg.date_names.en.season[month]] then -- xlate = cfg.date_names.inv_local_season[cfg.date_names.en.season[month]]; -- end -- elseif cfg.date_names.en.named[month] then -- named dates -- if cfg.date_names.inv_local_named[cfg.date_names.en.named[month]] then -- xlate = cfg.date_names.inv_local_named[cfg.date_names.en.named[month]]; -- end -- else -- xlate=nil; -- not an English month name; could be local language month name ---- mode = nil; -- not an English month name; could be local language month name or an English season name -- end if xlate then -- if mode then -- might be a season -- xlate = lang_object:formatDate(mode, '1' .. month); -- translate the month name to this local language date = mw.ustring.gsub (date, month, xlate); -- replace the English with the translation date_parameters_list[param_name].val = date; -- save the translated date modified = true; end end if xlt_dig then -- shall we also translate digits? date = date:gsub ('%d', cfg.date_names.xlate_digits); -- translate digits from Western to 'local digits' date_parameters_list[param_name].val = date; -- save the translated date modified = true; end end end return modified; end --[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >-------------------------------------- Sets local imported functions table to same (live or sandbox) as that used by the other modules. ]] local function set_selected_modules (cfg_table_ptr, utilities_page_ptr) add_prop_cat = utilities_page_ptr.add_prop_cat ; -- import functions from selected Module:Citation/CS1/Utilities module is_set = utilities_page_ptr.is_set; in_array = utilities_page_ptr.in_array; set_message = utilities_page_ptr.set_message; substitute = utilities_page_ptr.substitute; wrap_style = utilities_page_ptr.wrap_style; cfg = cfg_table_ptr; -- import tables from selected Module:Citation/CS1/Configuration end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { -- return exported functions dates = dates, year_date_check = year_date_check, reformat_dates = reformat_dates, date_hyphen_to_dash = date_hyphen_to_dash, date_name_xlate = date_name_xlate, set_selected_modules = set_selected_modules } d0271b200019639fd12f2b6c5e53be0e844e8453 Module:Citation/CS1/Identifiers 828 55 126 125 2022-09-04T15:24:37Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local has_accept_as_written, is_set, in_array, set_message, select_one, -- functions in Module:Citation/CS1/Utilities substitute, make_wikilink; local z; -- table of tables defined in Module:Citation/CS1/Utilities local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration --[[--------------------------< P A G E S C O P E V A R I A B L E S >-------------------------------------- declare variables here that have page-wide scope that are not brought in from other modules; that are created here and used here ]] local auto_link_urls = {}; -- holds identifier URLs for those identifiers that can auto-link |title= --============================<< H E L P E R F U N C T I O N S >>============================================ --[[--------------------------< W I K I D A T A _ A R T I C L E _ N A M E _ G E T >---------------------------- as an aid to internationalizing identifier-label wikilinks, gets identifier article names from Wikidata. returns :<lang code>:<article title> when <q> has an <article title> for <lang code>; nil else for identifiers that do not have q, returns nil for wikis that do not have mw.wikibase installed, returns nil ]] local function wikidata_article_name_get (q) if not is_set (q) or (q and not mw.wikibase) then -- when no q number or when a q number but mw.wikibase not installed on this wiki return nil; -- abandon end local wd_article; local this_wiki_code = cfg.this_wiki_code; -- Wikipedia subdomain; 'en' for en.wikipedia.org wd_article = mw.wikibase.getSitelink (q, this_wiki_code .. 'wiki'); -- fetch article title from WD; nil when no title available at this wiki if wd_article then wd_article = table.concat ({':', this_wiki_code, ':', wd_article}); -- interwiki-style link without brackets if taken from WD; leading colon required end return wd_article; -- article title from WD; nil else end --[[--------------------------< L I N K _ L A B E L _ M A K E >------------------------------------------------ common function to create identifier link label from handler table or from Wikidata returns the first available of 1. redirect from local wiki's handler table (if enabled) 2. Wikidata (if there is a Wikidata entry for this identifier in the local wiki's language) 3. label specified in the local wiki's handler table ]] local function link_label_make (handler) local wd_article; if not (cfg.use_identifier_redirects and is_set (handler.redirect)) then -- redirect has priority so if enabled and available don't fetch from Wikidata because expensive wd_article = wikidata_article_name_get (handler.q); -- if Wikidata has an article title for this wiki, get it; end return (cfg.use_identifier_redirects and is_set (handler.redirect) and handler.redirect) or wd_article or handler.link; end --[[--------------------------< E X T E R N A L _ L I N K _ I D >---------------------------------------------- Formats a wiki-style external link ]] local function external_link_id (options) local url_string = options.id; local ext_link; local this_wiki_code = cfg.this_wiki_code; -- Wikipedia subdomain; 'en' for en.wikipedia.org local wd_article; -- article title from Wikidata if options.encode == true or options.encode == nil then url_string = mw.uri.encode (url_string, 'PATH'); end if options.auto_link and is_set (options.access) then auto_link_urls[options.auto_link] = table.concat ({options.prefix, url_string, options.suffix}); end ext_link = mw.ustring.format ('[%s%s%s %s]', options.prefix, url_string, options.suffix or "", mw.text.nowiki (options.id)); if is_set (options.access) then ext_link = substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[options.access].class, cfg.presentation[options.access].title, ext_link}); -- add the free-to-read / paywall lock end return table.concat ({ make_wikilink (link_label_make (options), options.label), -- redirect, Wikidata link, or locally specified link (in that order) options.separator or '&nbsp;', ext_link }); end --[[--------------------------< I N T E R N A L _ L I N K _ I D >---------------------------------------------- Formats a wiki-style internal link TODO: Does not currently need to support options.access, options.encode, auto-linking and COinS (as in external_link_id), but may be needed in the future for :m:Interwiki_map custom-prefixes like :arxiv:, :bibcode:, :DOI:, :hdl:, :ISSN:, :JSTOR:, :Openlibrary:, :PMID:, :RFC:. ]] local function internal_link_id (options) local id = mw.ustring.gsub (options.id, '%d', cfg.date_names.local_digits); -- translate 'local' digits to Western 0-9 return table.concat ( { make_wikilink (link_label_make (options), options.label), -- wiki-link the identifier label options.separator or '&nbsp;', -- add the separator make_wikilink ( table.concat ( { options.prefix, id, -- translated to Western digits options.suffix or '' }), substitute (cfg.presentation['bdi'], {'', mw.text.nowiki (options.id)}) -- bdi tags to prevent Latin script identifiers from being reversed at RTL language wikis ); -- nowiki because MediaWiki still has magic links for ISBN and the like; TODO: is it really required? }); end --[[--------------------------< I S _ E M B A R G O E D >------------------------------------------------------ Determines if a PMC identifier's online version is embargoed. Compares the date in |pmc-embargo-date= against today's date. If embargo date is in the future, returns the content of |pmc-embargo-date=; otherwise, returns an empty string because the embargo has expired or because |pmc-embargo-date= was not set in this cite. ]] local function is_embargoed (embargo) if is_set (embargo) then local lang = mw.getContentLanguage(); local good1, embargo_date, todays_date; good1, embargo_date = pcall (lang.formatDate, lang, 'U', embargo); todays_date = lang:formatDate ('U'); if good1 then -- if embargo date is a good date if tonumber (embargo_date) >= tonumber (todays_date) then -- is embargo date is in the future? return embargo; -- still embargoed else set_message ('maint_pmc_embargo'); -- embargo has expired; add main cat return ''; -- unset because embargo has expired end end end return ''; -- |pmc-embargo-date= not set return empty string end --[=[-------------------------< I S _ V A L I D _ B I O R X I V _ D A T E >------------------------------------ returns true if: 2019-12-11T00:00Z <= biorxiv_date < today + 2 days The dated form of biorxiv identifier has a start date of 2019-12-11. The Unix timestamp for that date is {{#time:U|2019-12-11}} = 1576022400 biorxiv_date is the date provided in those |biorxiv= parameter values that are dated at time 00:00:00 UTC today is the current date at time 00:00:00 UTC plus 48 hours if today is 2015-01-01T00:00:00 then adding 24 hours gives 2015-01-02T00:00:00 – one second more than today adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow This function does not work if it is fed month names for languages other than English. Wikimedia #time: parser apparently doesn't understand non-English date month names. This function will always return false when the date contains a non-English month name because good1 is false after the call to lang_object.formatDate(). To get around that call this function with date parts and create a YYYY-MM-DD format date. ]=] local function is_valid_biorxiv_date (y, m, d) local biorxiv_date = table.concat ({y, m, d}, '-'); -- make ymd date local good1, good2; local biorxiv_ts, tomorrow_ts; -- to hold Unix timestamps representing the dates local lang_object = mw.getContentLanguage(); good1, biorxiv_ts = pcall (lang_object.formatDate, lang_object, 'U', biorxiv_date); -- convert biorxiv_date value to Unix timestamp good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow if good1 and good2 then -- lang.formatDate() returns a timestamp in the local script which tonumber() may not understand biorxiv_ts = tonumber (biorxiv_ts) or lang_object:parseFormattedNumber (biorxiv_ts); -- convert to numbers for the comparison; tomorrow_ts = tonumber (tomorrow_ts) or lang_object:parseFormattedNumber (tomorrow_ts); else return false; -- one or both failed to convert to Unix timestamp end return ((1576022400 <= biorxiv_ts) and (biorxiv_ts < tomorrow_ts)) -- 2012-12-11T00:00Z <= biorxiv_date < tomorrow's date end --[[--------------------------< IS _ V A L I D _ I S X N >----------------------------------------------------- ISBN-10 and ISSN validator code calculates checksum across all ISBN/ISSN digits including the check digit. ISBN-13 is checked in isbn(). If the number is valid the result will be 0. Before calling this function, ISBN/ISSN must be checked for length and stripped of dashes, spaces and other non-ISxN characters. ]] local function is_valid_isxn (isxn_str, len) local temp = 0; isxn_str = { isxn_str:byte(1, len) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39, 'X' → 0x58 len = len + 1; -- adjust to be a loop counter for i, v in ipairs (isxn_str) do -- loop through all of the bytes and calculate the checksum if v == string.byte ("X" ) then -- if checkdigit is X (compares the byte value of 'X' which is 0x58) temp = temp + 10 * (len - i); -- it represents 10 decimal else temp = temp + tonumber (string.char (v) )*(len-i); end end return temp % 11 == 0; -- returns true if calculation result is zero end --[[--------------------------< IS _ V A L I D _ I S X N _ 1 3 >----------------------------------------------- ISBN-13 and ISMN validator code calculates checksum across all 13 ISBN/ISMN digits including the check digit. If the number is valid, the result will be 0. Before calling this function, ISBN-13/ISMN must be checked for length and stripped of dashes, spaces and other non-ISxN-13 characters. ]] local function is_valid_isxn_13 (isxn_str) local temp=0; isxn_str = { isxn_str:byte(1, 13) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39 for i, v in ipairs (isxn_str) do temp = temp + (3 - 2*(i % 2)) * tonumber (string.char (v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit end return temp % 10 == 0; -- sum modulo 10 is zero when ISBN-13/ISMN is correct end --[[--------------------------< N O R M A L I Z E _ L C C N >-------------------------------------------------- LCCN normalization (http://www.loc.gov/marc/lccn-namespace.html#normalization) 1. Remove all blanks. 2. If there is a forward slash (/) in the string, remove it, and remove all characters to the right of the forward slash. 3. If there is a hyphen in the string: a. Remove it. b. Inspect the substring following (to the right of) the (removed) hyphen. Then (and assuming that steps 1 and 2 have been carried out): 1. All these characters should be digits, and there should be six or less. (not done in this function) 2. If the length of the substring is less than 6, left-fill the substring with zeroes until the length is six. Returns a normalized LCCN for lccn() to validate. There is no error checking (step 3.b.1) performed in this function. ]] local function normalize_lccn (lccn) lccn = lccn:gsub ("%s", ""); -- 1. strip whitespace if nil ~= string.find (lccn, '/') then lccn = lccn:match ("(.-)/"); -- 2. remove forward slash and all character to the right of it end local prefix local suffix prefix, suffix = lccn:match ("(.+)%-(.+)"); -- 3.a remove hyphen by splitting the string into prefix and suffix if nil ~= suffix then -- if there was a hyphen suffix = string.rep("0", 6-string.len (suffix)) .. suffix; -- 3.b.2 left fill the suffix with 0s if suffix length less than 6 lccn = prefix..suffix; -- reassemble the LCCN end return lccn; end --============================<< I D E N T I F I E R F U N C T I O N S >>==================================== --[[--------------------------< A R X I V >-------------------------------------------------------------------- See: http://arxiv.org/help/arxiv_identifier format and error check arXiv identifier. There are three valid forms of the identifier: the first form, valid only between date codes 9107 and 0703, is: arXiv:<archive>.<class>/<date code><number><version> where: <archive> is a string of alpha characters - may be hyphenated; no other punctuation <class> is a string of alpha characters - may be hyphenated; no other punctuation; not the same as |class= parameter which is not supported in this form <date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01 first digit of YY for this form can only 9 and 0 <number> is a three-digit number <version> is a 1 or more digit number preceded with a lowercase v; no spaces (undocumented) the second form, valid from April 2007 through December 2014 is: arXiv:<date code>.<number><version> where: <date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01 <number> is a four-digit number <version> is a 1 or more digit number preceded with a lowercase v; no spaces the third form, valid from January 2015 is: arXiv:<date code>.<number><version> where: <date code> and <version> are as defined for 0704-1412 <number> is a five-digit number ]] local function arxiv (options) local id = options.id; local class = options.Class; -- TODO: lowercase? local handler = options.handler; local year, month, version; local err_msg = false; -- assume no error message local text; -- output text if id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$") or id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%dv%d+$") then -- test for the 9107-0703 format with or without version year, month = id:match("^%a[%a%.%-]+/([90]%d)([01]%d)%d%d%d[v%d]*$"); year = tonumber (year); month = tonumber (month); if ((not (90 < year or 8 > year)) or (1 > month or 12 < month)) or -- if invalid year or invalid month ((91 == year and 7 > month) or (7 == year and 3 < month)) then -- if years ok, are starting and ending months ok? err_msg = true; -- flag for error message end elseif id:match("^%d%d[01]%d%.%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%dv%d+$") then -- test for the 0704-1412 with or without version year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d[v%d]*$"); year = tonumber (year); month = tonumber (month); if ((7 > year) or (14 < year) or (1 > month or 12 < month)) or -- is year invalid or is month invalid? (doesn't test for future years) ((7 == year) and (4 > month)) then -- when year is 07, is month invalid (before April)? err_msg = true; -- flag for error message end elseif id:match("^%d%d[01]%d%.%d%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%d%dv%d+$") then -- test for the 1501- format with or without version year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d%d[v%d]*$"); year = tonumber (year); month = tonumber (month); if ((15 > year) or (1 > month or 12 < month)) then -- is year invalid or is month invalid? (doesn't test for future years) err_msg = true; -- flag for error message end else err_msg = true; -- not a recognized format; flag for error message end if err_msg then options.coins_list_t['ARXIV'] = nil; -- when error, unset so not included in COinS end local err_msg_t = {}; if err_msg then set_message ('err_bad_arxiv'); end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access}); if is_set (class) then if id:match ('^%d+') then text = table.concat ({text, ' [[//arxiv.org/archive/', class, ' ', class, ']]'}); -- external link within square brackets, not wikilink else set_message ('err_class_ignored'); end end return text; end --[[--------------------------< B I B C O D E >-------------------------------------------------------------------- Validates (sort of) and formats a bibcode ID. Format for bibcodes is specified here: http://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes But, this: 2015arXiv151206696F is apparently valid so apparently, the only things that really matter are length, 19 characters and first four digits must be a year. This function makes these tests: length must be 19 characters characters in position 1–4 must be digits and must represent a year in the range of 1000 – next year 5 must be a letter 6–8 must be letter, digit, ampersand, or dot (ampersand cannot directly precede a dot; &. ) 9–18 must be letter, digit, or dot 19 must be a letter or dot ]] local function bibcode (options) local id = options.id; local access = options.access; local handler = options.handler; local err_type; local err_msg = ''; local year; local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}); if 19 ~= id:len() then err_type = cfg.err_msg_supl.length; else year = id:match ("^(%d%d%d%d)[%a][%w&%.][%w&%.][%w&%.][%w.]+[%a%.]$"); if not year then -- if nil then no pattern match err_type = cfg.err_msg_supl.value; -- so value error else local next_year = tonumber (os.date ('%Y')) + 1; -- get the current year as a number and add one for next year year = tonumber (year); -- convert year portion of bibcode to a number if (1000 > year) or (year > next_year) then err_type = cfg.err_msg_supl.year; -- year out of bounds end if id:find('&%.') then err_type = cfg.err_msg_supl.journal; -- journal abbreviation must not have '&.' (if it does it's missing a letter) end end end if is_set (err_type) then -- if there was an error detected set_message ('err_bad_bibcode', {err_type}); options.coins_list_t['BIBCODE'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< B I O R X I V >----------------------------------------------------------------- Format bioRxiv ID and do simple error checking. Before 2019-12-11, biorXiv IDs were 10.1101/ followed by exactly 6 digits. After 2019-12-11, biorXiv IDs retained the six-digit identifier but prefixed that with a yyyy.mm.dd. date and suffixed with an optional version identifier. The bioRxiv ID is the string of characters: https://doi.org/10.1101/078733 -> 10.1101/078733 or a date followed by a six-digit number followed by an optional version indicator 'v' and one or more digits: https://www.biorxiv.org/content/10.1101/2019.12.11.123456v2 -> 10.1101/2019.12.11.123456v2 see https://www.biorxiv.org/about-biorxiv ]] local function biorxiv (options) local id = options.id; local handler = options.handler; local err_msg = true; -- flag; assume that there will be an error local patterns = { '^10.1101/%d%d%d%d%d%d$', -- simple 6-digit identifier (before 2019-12-11) '^10.1101/(20[1-9]%d)%.([01]%d)%.([0-3]%d)%.%d%d%d%d%d%dv%d+$', -- y.m.d. date + 6-digit identifier + version (after 2019-12-11) '^10.1101/(20[1-9]%d)%.([01]%d)%.([0-3]%d)%.%d%d%d%d%d%d$', -- y.m.d. date + 6-digit identifier (after 2019-12-11) } for _, pattern in ipairs (patterns) do -- spin through the patterns looking for a match if id:match (pattern) then local y, m, d = id:match (pattern); -- found a match, attempt to get year, month and date from the identifier if m then -- m is nil when id is the six-digit form if not is_valid_biorxiv_date (y, m, d) then -- validate the encoded date; TODO: don't ignore leap-year and actual month lengths ({{#time:}} is a poor date validator) break; -- date fail; break out early so we don't unset the error message end end err_msg = nil; -- we found a match so unset the error message break; -- and done end end -- err_cat remains set here when no match if err_msg then options.coins_list_t['BIORXIV'] = nil; -- when error, unset so not included in COinS set_message ('err_bad_biorxiv'); -- and set the error message end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access}); end --[[--------------------------< C I T E S E E R X >------------------------------------------------------------ CiteSeerX use their own notion of "doi" (not to be confused with the identifiers resolved via doi.org). The description of the structure of this identifier can be found at Help_talk:Citation_Style_1/Archive_26#CiteSeerX_id_structure ]] local function citeseerx (options) local id = options.id; local handler = options.handler; local matched; local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access}); matched = id:match ("^10%.1%.1%.[1-9]%d?%d?%d?%.[1-9]%d?%d?%d?$"); if not matched then set_message ('err_bad_citeseerx' ); options.coins_list_t['CITESEERX'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< D O I >------------------------------------------------------------------------ Formats a DOI and checks for DOI errors. DOI names contain two parts: prefix and suffix separated by a forward slash. Prefix: directory indicator '10.' followed by a registrant code Suffix: character string of any length chosen by the registrant This function checks a DOI name for: prefix/suffix. If the DOI name contains spaces or endashes, or, if it ends with a period or a comma, this function will emit a bad_doi error message. DOI names are case-insensitive and can incorporate any printable Unicode characters so the test for spaces, endash, and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely if ever used in DOI names. ]] local function doi (options) local id = options.id; local inactive = options.DoiBroken local access = options.access; local ignore_invalid = options.accept; local handler = options.handler; local err_flag; local text; if is_set (inactive) then local inactive_year = inactive:match("%d%d%d%d") or ''; -- try to get the year portion from the inactive date local inactive_month, good; if is_set (inactive_year) then if 4 < inactive:len() then -- inactive date has more than just a year (could be anything) local lang_obj = mw.getContentLanguage(); -- get a language object for this wiki good, inactive_month = pcall (lang_obj.formatDate, lang_obj, 'F', inactive); -- try to get the month name from the inactive date if not good then inactive_month = nil; -- something went wrong so make sure this is unset end end else inactive_year = nil; -- |doi-broken-date= has something but it isn't a date end if is_set (inactive_year) and is_set (inactive_month) then set_message ('maint_doi_inactive_dated', {inactive_year, inactive_month, ' '}); elseif is_set (inactive_year) then set_message ('maint_doi_inactive_dated', {inactive_year, '', ''}); else set_message ('maint_doi_inactive'); end inactive = " (" .. cfg.messages['inactive'] .. ' ' .. inactive .. ')'; end local registrant = mw.ustring.match (id, '^10%.([^/]+)/[^%s–]-[^%.,]$'); -- registrant set when DOI has the proper basic form local registrant_err_patterns = { -- these patterns are for code ranges that are not supported '^[^1-3]%d%d%d%d%.%d%d*$', -- 5 digits with subcode (0xxxx, 40000+); accepts: 10000–39999 '^[^1-5]%d%d%d%d$', -- 5 digits without subcode (0xxxx, 60000+); accepts: 10000–59999 '^[^1-9]%d%d%d%.%d%d*$', -- 4 digits with subcode (0xxx); accepts: 1000–9999 '^[^1-9]%d%d%d$', -- 4 digits without subcode (0xxx); accepts: 1000–9999 '^%d%d%d%d%d%d+', -- 6 or more digits '^%d%d?%d?$', -- less than 4 digits without subcode (with subcode is legitimate) '^5555$', -- test registrant will never resolve '[^%d%.]', -- any character that isn't a digit or a dot } if not ignore_invalid then if registrant then -- when DOI has proper form for i, pattern in ipairs (registrant_err_patterns) do -- spin through error patterns if registrant:match (pattern) then -- to validate registrant codes err_flag = set_message ('err_bad_doi'); -- when found, mark this DOI as bad break; -- and done end end else err_flag = set_message ('err_bad_doi'); -- invalid directory or malformed end else set_message ('maint_doi_ignore'); end if err_flag then options.coins_list_t['DOI'] = nil; -- when error, unset so not included in COinS end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access, auto_link = not (err_flag or is_set (inactive) or ignore_invalid) and 'doi' or nil -- do not auto-link when |doi-broken-date= has a value or when there is a DOI error or (to play it safe, after all, auto-linking is not essential) when invalid DOIs are ignored }) .. (inactive or ''); return text; end --[[--------------------------< H D L >------------------------------------------------------------------------ Formats an HDL with minor error checking. HDL names contain two parts: prefix and suffix separated by a forward slash. Prefix: character string using any character in the UCS-2 character set except '/' Suffix: character string of any length using any character in the UCS-2 character set chosen by the registrant This function checks a HDL name for: prefix/suffix. If the HDL name contains spaces, endashes, or, if it ends with a period or a comma, this function will emit a bad_hdl error message. HDL names are case-insensitive and can incorporate any printable Unicode characters so the test for endashes and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely if ever used in HDLs. Query string parameters are named here: http://www.handle.net/proxy_servlet.html. query strings are not displayed but since '?' is an allowed character in an HDL, '?' followed by one of the query parameters is the only way we have to detect the query string so that it isn't URL-encoded with the rest of the identifier. ]] local function hdl (options) local id = options.id; local access = options.access; local handler = options.handler; local query_params = { -- list of known query parameters from http://www.handle.net/proxy_servlet.html 'noredirect', 'ignore_aliases', 'auth', 'cert', 'index', 'type', 'urlappend', 'locatt', 'action', } local hdl, suffix, param = id:match ('(.-)(%?(%a+).+)$'); -- look for query string local found; if hdl then -- when there are query strings, this is the handle identifier portion for _, q in ipairs (query_params) do -- spin through the list of query parameters if param:match ('^' .. q) then -- if the query string begins with one of the parameters found = true; -- announce a find break; -- and stop looking end end end if found then id = hdl; -- found so replace id with the handle portion; this will be URL-encoded, suffix will not else suffix = ''; -- make sure suffix is empty string for concatenation else end local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, suffix = suffix, separator = handler.separator, encode = handler.encode, access = access}) if nil == id:match("^[^%s–]-/[^%s–]-[^%.,]$") then -- HDL must contain a forward slash, must not contain spaces, endashes, and must not end with period or comma set_message ('err_bad_hdl' ); options.coins_list_t['HDL'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< I S B N >---------------------------------------------------------------------- Determines whether an ISBN string is valid ]] local function isbn (options) local isbn_str = options.id; local ignore_invalid = options.accept; local handler = options.handler; local function return_result (check, err_type) -- local function to handle the various returns local ISBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect, prefix = handler.prefix, id = isbn_str, separator = handler.separator}); if ignore_invalid then -- if ignoring ISBN errors set_message ('maint_isbn_ignore'); -- add a maint category even when there is no error else -- here when not ignoring if not check then -- and there is an error options.coins_list_t['ISBN'] = nil; -- when error, unset so not included in COinS set_message ('err_bad_isbn', err_type); -- set an error message return ISBN; -- return id text end end return ISBN; -- return id text end if nil ~= isbn_str:match ('[^%s-0-9X]') then return return_result (false, cfg.err_msg_supl.char); -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X end local id = isbn_str:gsub ('[%s-]', ''); -- remove hyphens and whitespace local len = id:len(); if len ~= 10 and len ~= 13 then return return_result (false, cfg.err_msg_supl.length); -- fail if incorrect length end if len == 10 then if id:match ('^%d*X?$') == nil then -- fail if isbn_str has 'X' anywhere but last position return return_result (false, cfg.err_msg_supl.form); end if not is_valid_isxn (id, 10) then -- test isbn-10 for numerical validity return return_result (false, cfg.err_msg_supl.check); -- fail if isbn-10 is not numerically valid end if id:find ('^63[01]') then -- 630xxxxxxx and 631xxxxxxx are (apparently) not valid isbn group ids but are used by amazon as numeric identifiers (asin) return return_result (false, cfg.err_msg_supl.group); -- fail if isbn-10 begins with 630/1 end return return_result (true, cfg.err_msg_supl.check); -- pass if isbn-10 is numerically valid else if id:match ('^%d+$') == nil then return return_result (false, cfg.err_msg_supl.char); -- fail if ISBN-13 is not all digits end if id:match ('^97[89]%d*$') == nil then return return_result (false, cfg.err_msg_supl.prefix); -- fail when ISBN-13 does not begin with 978 or 979 end if id:match ('^9790') then return return_result (false, cfg.err_msg_supl.group); -- group identifier '0' is reserved to ISMN end return return_result (is_valid_isxn_13 (id), cfg.err_msg_supl.check); end end --[[--------------------------< A S I N >---------------------------------------------------------------------- Formats a link to Amazon. Do simple error checking: ASIN must be mix of 10 numeric or uppercase alpha characters. If a mix, first character must be uppercase alpha; if all numeric, ASINs must be 10-digit ISBN. If 10-digit ISBN, add a maintenance category so a bot or AWB script can replace |asin= with |isbn=. Error message if not 10 characters, if not ISBN-10, if mixed and first character is a digit. |asin=630....... and |asin=631....... are (apparently) not a legitimate ISBN though it checksums as one; these do not cause this function to emit the maint_asin message This function is positioned here because it calls isbn() ]] local function asin (options) local id = options.id; local domain = options.ASINTLD; local err_flag; if not id:match("^[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$") then err_flag = set_message ('err_bad_asin'); -- ASIN is not a mix of 10 uppercase alpha and numeric characters else if id:match("^%d%d%d%d%d%d%d%d%d[%dX]$") then -- if 10-digit numeric (or 9 digits with terminal X) if is_valid_isxn (id, 10) then -- see if ASIN value is or validates as ISBN-10 if not id:find ('^63[01]') then -- 630xxxxxxx and 631xxxxxxx are (apparently) not a valid isbn prefixes but are used by amazon as a numeric identifier err_flag = set_message ('err_bad_asin'); -- ASIN has ISBN-10 form but begins with something other than 630/1 so probably an isbn end elseif not is_set (err_flag) then err_flag = set_message ('err_bad_asin'); -- ASIN is not ISBN-10 end elseif not id:match("^%u[%d%u]+$") then err_flag = set_message ('err_bad_asin'); -- asin doesn't begin with uppercase alpha end end if (not is_set (domain)) or in_array (domain, {'us'}) then -- default: United States domain = "com"; elseif in_array (domain, {'jp', 'uk'}) then -- Japan, United Kingdom domain = "co." .. domain; elseif in_array (domain, {'z.cn'}) then -- China domain = "cn"; elseif in_array (domain, {'au', 'br', 'mx', 'sg', 'tr'}) then -- Australia, Brazil, Mexico, Singapore, Turkey domain = "com." .. domain; elseif not in_array (domain, {'ae', 'ca', 'cn', 'de', 'es', 'fr', 'in', 'it', 'nl', 'pl', 'sa', 'se', 'co.jp', 'co.uk', 'com', 'com.au', 'com.br', 'com.mx', 'com.sg', 'com.tr'}) then -- Arabic Emirates, Canada, China, Germany, Spain, France, Indonesia, Italy, Netherlands, Poland, Saudi Arabia, Sweden (as of 2021-03 Austria (.at), Liechtenstein (.li) and Switzerland (.ch) still redirect to the German site (.de) with special settings, so don't maintain local ASINs for them) err_flag = set_message ('err_bad_asin_tld'); -- unsupported asin-tld value end local handler = options.handler; if not is_set (err_flag) then options.coins_list_t['ASIN'] = handler.prefix .. domain .. "/dp/" .. id; -- asin for coins else options.coins_list_t['ASIN'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix .. domain .. "/dp/", id = id, encode = handler.encode, separator = handler.separator}) end --[[--------------------------< I S M N >---------------------------------------------------------------------- Determines whether an ISMN string is valid. Similar to ISBN-13, ISMN is 13 digits beginning 979-0-... and uses the same check digit calculations. See http://www.ismn-international.org/download/Web_ISMN_Users_Manual_2008-6.pdf section 2, pages 9–12. ismn value not made part of COinS metadata because we don't have a url or isn't a COinS-defined identifier (rft.xxx) or an identifier registered at info-uri.info (info:) ]] local function ismn (options) local id = options.id; local handler = options.handler; local text; local valid_ismn = true; local id_copy; id_copy = id; -- save a copy because this testing is destructive id = id:gsub ('[%s-]', ''); -- remove hyphens and white space if 13 ~= id:len() or id:match ("^9790%d*$" ) == nil then -- ISMN must be 13 digits and begin with 9790 valid_ismn = false; else valid_ismn=is_valid_isxn_13 (id); -- validate ISMN end -- text = internal_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, -- use this (or external version) when there is some place to link to -- prefix = handler.prefix, id = id_copy, separator = handler.separator, encode = handler.encode}) text = table.concat ( -- because no place to link to yet { make_wikilink (link_label_make (handler), handler.label), handler.separator, id_copy }); if false == valid_ismn then options.coins_list_t['ISMN'] = nil; -- when error, unset so not included in COinS; not really necessary here because ismn not made part of COinS set_message ('err_bad_ismn'); -- create an error message if the ISMN is invalid end return text; end --[[--------------------------< I S S N >---------------------------------------------------------------------- Validate and format an ISSN. This code fixes the case where an editor has included an ISSN in the citation but has separated the two groups of four digits with a space. When that condition occurred, the resulting link looked like this: |issn=0819 4327 gives: [http://www.worldcat.org/issn/0819 4327 0819 4327] -- can't have spaces in an external link This code now prevents that by inserting a hyphen at the ISSN midpoint. It also validates the ISSN for length and makes sure that the checkdigit agrees with the calculated value. Incorrect length (8 digits), characters other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check ISSN error message. The ISSN is always displayed with a hyphen, even if the ISSN was given as a single group of 8 digits. ]] local function issn (options) local id = options.id; local handler = options.handler; local ignore_invalid = options.accept; local issn_copy = id; -- save a copy of unadulterated ISSN; use this version for display if ISSN does not validate local text; local valid_issn = true; id = id:gsub ('[%s-]', ''); -- remove hyphens and whitespace if 8 ~= id:len() or nil == id:match ("^%d*X?$" ) then -- validate the ISSN: 8 digits long, containing only 0-9 or X in the last position valid_issn = false; -- wrong length or improper character else valid_issn = is_valid_isxn (id, 8); -- validate ISSN end if true == valid_issn then id = string.sub (id, 1, 4 ) .. "-" .. string.sub (id, 5 ); -- if valid, display correctly formatted version else id = issn_copy; -- if not valid, show the invalid ISSN with error message end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}) if ignore_invalid then set_message ('maint_issn_ignore'); else if false == valid_issn then options.coins_list_t['ISSN'] = nil; -- when error, unset so not included in COinS set_message ('err_bad_issn', (options.hkey == 'EISSN') and 'e' or ''); -- create an error message if the ISSN is invalid end end return text; end --[[--------------------------< J F M >----------------------------------------------------------------------- A numerical identifier in the form nn.nnnn.nn ]] local function jfm (options) local id = options.id; local handler = options.handler; local id_num; id_num = id:match ('^[Jj][Ff][Mm](.*)$'); -- identifier with jfm prefix; extract identifier if is_set (id_num) then set_message ('maint_jfm_format'); else -- plain number without JFM prefix id_num = id; -- if here id does not have prefix end if id_num and id_num:match('^%d%d%.%d%d%d%d%.%d%d$') then id = id_num; -- jfm matches pattern else set_message ('err_bad_jfm' ); -- set an error message options.coins_list_t['JFM'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< J S T O R >-------------------------------------------------------------------- Format a JSTOR with some error checking ]] local function jstor (options) local id = options.id; local access = options.access; local handler = options.handler; if id:find ('[Jj][Ss][Tt][Oo][Rr]') or id:find ('^https?://') or id:find ('%s') then set_message ('err_bad_jstor'); -- set an error message options.coins_list_t['JSTOR'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}); end --[[--------------------------< L C C N >---------------------------------------------------------------------- Format LCCN link and do simple error checking. LCCN is a character string 8-12 characters long. The length of the LCCN dictates the character type of the first 1-3 characters; the rightmost eight are always digits. http://info-uri.info/registry/OAIHandler?verb=GetRecord&metadataPrefix=reg&identifier=info:lccn/ length = 8 then all digits length = 9 then lccn[1] is lowercase alpha length = 10 then lccn[1] and lccn[2] are both lowercase alpha or both digits length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lowercase alpha or both digits length = 12 then lccn[1] and lccn[2] are both lowercase alpha ]] local function lccn (options) local lccn = options.id; local handler = options.handler; local err_flag; -- presume that LCCN is valid local id = lccn; -- local copy of the LCCN id = normalize_lccn (id); -- get canonical form (no whitespace, hyphens, forward slashes) local len = id:len(); -- get the length of the LCCN if 8 == len then if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) err_flag = set_message ('err_bad_lccn'); -- set an error message end elseif 9 == len then -- LCCN should be adddddddd if nil == id:match("%l%d%d%d%d%d%d%d%d") then -- does it match our pattern? err_flag = set_message ('err_bad_lccn'); -- set an error message end elseif 10 == len then -- LCCN should be aadddddddd or dddddddddd if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) ... if nil == id:match("^%l%l%d%d%d%d%d%d%d%d") then -- ... see if it matches our pattern err_flag = set_message ('err_bad_lccn'); -- no match, set an error message end end elseif 11 == len then -- LCCN should be aaadddddddd or adddddddddd if not (id:match("^%l%l%l%d%d%d%d%d%d%d%d") or id:match("^%l%d%d%d%d%d%d%d%d%d%d")) then -- see if it matches one of our patterns err_flag = set_message ('err_bad_lccn'); -- no match, set an error message end elseif 12 == len then -- LCCN should be aadddddddddd if not id:match("^%l%l%d%d%d%d%d%d%d%d%d%d") then -- see if it matches our pattern err_flag = set_message ('err_bad_lccn'); -- no match, set an error message end else err_flag = set_message ('err_bad_lccn'); -- wrong length, set an error message end if not is_set (err_flag) and nil ~= lccn:find ('%s') then err_flag = set_message ('err_bad_lccn'); -- lccn contains a space, set an error message end if is_set (err_flag) then options.coins_list_t['LCCN'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = lccn, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< M R >-------------------------------------------------------------------------- A seven digit number; if not seven digits, zero-fill leading digits to make seven digits. ]] local function mr (options) local id = options.id; local handler = options.handler; local id_num; local id_len; id_num = id:match ('^[Mm][Rr](%d+)$'); -- identifier with mr prefix if is_set (id_num) then set_message ('maint_mr_format'); -- add maint cat else -- plain number without mr prefix id_num = id:match ('^%d+$'); -- if here id is all digits end id_len = id_num and id_num:len() or 0; if (7 >= id_len) and (0 ~= id_len) then id = string.rep ('0', 7-id_len) .. id_num; -- zero-fill leading digits else set_message ('err_bad_mr'); -- set an error message options.coins_list_t['MR'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< O C L C >---------------------------------------------------------------------- Validate and format an OCLC ID. https://www.oclc.org/batchload/controlnumber.en.html {{dead link}} archived at: https://web.archive.org/web/20161228233804/https://www.oclc.org/batchload/controlnumber.en.html ]] local function oclc (options) local id = options.id; local handler = options.handler; local number; if id:match('^ocm%d%d%d%d%d%d%d%d$') then -- ocm prefix and 8 digits; 001 field (12 characters) number = id:match('ocm(%d+)'); -- get the number elseif id:match('^ocn%d%d%d%d%d%d%d%d%d$') then -- ocn prefix and 9 digits; 001 field (12 characters) number = id:match('ocn(%d+)'); -- get the number elseif id:match('^on%d%d%d%d%d%d%d%d%d%d+$') then -- on prefix and 10 or more digits; 001 field (12 characters) number = id:match('^on(%d%d%d%d%d%d%d%d%d%d+)$'); -- get the number elseif id:match('^%(OCoLC%)[1-9]%d*$') then -- (OCoLC) prefix and variable number digits; no leading zeros; 035 field number = id:match('%(OCoLC%)([1-9]%d*)'); -- get the number if 9 < number:len() then number = nil; -- constrain to 1 to 9 digits; change this when OCLC issues 10-digit numbers end elseif id:match('^%d+$') then -- no prefix number = id; -- get the number if 10 < number:len() then number = nil; -- constrain to 1 to 10 digits; change this when OCLC issues 11-digit numbers end end if number then -- proper format id = number; -- exclude prefix, if any, from external link else set_message ('err_bad_oclc') -- add an error message if the id is malformed options.coins_list_t['OCLC'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< O P E N L I B R A R Y >-------------------------------------------------------- Formats an OpenLibrary link, and checks for associated errors. ]] local function openlibrary (options) local id = options.id; local access = options.access; local handler = options.handler; local ident, code = id:gsub('^OL', ''):match("^(%d+([AMW]))$"); -- strip optional OL prefix followed immediately by digits followed by 'A', 'M', or 'W'; local err_flag; local prefix = { -- these are appended to the handler.prefix according to code ['A']='authors/OL', ['M']='books/OL', ['W']='works/OL', ['X']='OL' -- not a code; spoof when 'code' in id is invalid }; if not ident then code = 'X'; -- no code or id completely invalid ident = id; -- copy id to ident so that we display the flawed identifier err_flag = set_message ('err_bad_ol'); end if not is_set (err_flag) then options.coins_list_t['OL'] = handler.prefix .. prefix[code] .. ident; -- experiment for ol coins else options.coins_list_t['OL'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix .. prefix[code], id = ident, separator = handler.separator, encode = handler.encode, access = access}); end --[[--------------------------< O S T I >---------------------------------------------------------------------- Format OSTI and do simple error checking. OSTIs are sequential numbers beginning at 1 and counting up. This code checks the OSTI to see that it contains only digits and is less than test_limit specified in the configuration; the value in test_limit will need to be updated periodically as more OSTIs are issued. NB. 1018 is the lowest OSTI number found in the wild (so far) and resolving OK on the OSTI site ]] local function osti (options) local id = options.id; local access = options.access; local handler = options.handler; if id:match("[^%d]") then -- if OSTI has anything but digits set_message ('err_bad_osti'); -- set an error message options.coins_list_t['OSTI'] = nil; -- when error, unset so not included in COinS else -- OSTI is only digits local id_num = tonumber (id); -- convert id to a number for range testing if 1018 > id_num or handler.id_limit < id_num then -- if OSTI is outside test limit boundaries set_message ('err_bad_osti'); -- set an error message options.coins_list_t['OSTI'] = nil; -- when error, unset so not included in COinS end end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}); end --[[--------------------------< P M C >------------------------------------------------------------------------ Format a PMC, do simple error checking, and check for embargoed articles. The embargo parameter takes a date for a value. If the embargo date is in the future the PMC identifier will not be linked to the article. If the embargo date is today or in the past, or if it is empty or omitted, then the PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].prefix. PMC embargo date testing is done in function is_embargoed () which is called earlier because when the citation has |pmc=<value> but does not have a |url= then |title= is linked with the PMC link. Function is_embargoed () returns the embargo date if the PMC article is still embargoed, otherwise it returns an empty string. PMCs are sequential numbers beginning at 1 and counting up. This code checks the PMC to see that it contains only digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically as more PMCs are issued. ]] local function pmc (options) local id = options.id; local embargo = options.Embargo; -- TODO: lowercase? local handler = options.handler; local err_flag; local id_num; local text; id_num = id:match ('^[Pp][Mm][Cc](%d+)$'); -- identifier with PMC prefix if is_set (id_num) then set_message ('maint_pmc_format'); else -- plain number without PMC prefix id_num = id:match ('^%d+$'); -- if here id is all digits end if is_set (id_num) then -- id_num has a value so test it id_num = tonumber (id_num); -- convert id_num to a number for range testing if 1 > id_num or handler.id_limit < id_num then -- if PMC is outside test limit boundaries err_flag = set_message ('err_bad_pmc'); -- set an error message else id = tostring (id_num); -- make sure id is a string end else -- when id format incorrect err_flag = set_message ('err_bad_pmc'); -- set an error message end if is_set (embargo) and is_set (is_embargoed (embargo)) then -- is PMC is still embargoed? text = table.concat ( -- still embargoed so no external link { make_wikilink (link_label_make (handler), handler.label), handler.separator, id, }); else text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, -- no embargo date or embargo has expired, ok to link to article prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access, auto_link = not err_flag and 'pmc' or nil -- do not auto-link when PMC has error }); end if err_flag then options.coins_list_t['PMC'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< P M I D >---------------------------------------------------------------------- Format PMID and do simple error checking. PMIDs are sequential numbers beginning at 1 and counting up. This code checks the PMID to see that it contains only digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically as more PMIDs are issued. ]] local function pmid (options) local id = options.id; local handler = options.handler; if id:match("[^%d]") then -- if PMID has anything but digits set_message ('err_bad_pmid'); -- set an error message options.coins_list_t['PMID'] = nil; -- when error, unset so not included in COinS else -- PMID is only digits local id_num = tonumber (id); -- convert id to a number for range testing if 1 > id_num or handler.id_limit < id_num then -- if PMID is outside test limit boundaries set_message ('err_bad_pmid'); -- set an error message options.coins_list_t['PMID'] = nil; -- when error, unset so not included in COinS end end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --[[--------------------------< R F C >------------------------------------------------------------------------ Format RFC and do simple error checking. RFCs are sequential numbers beginning at 1 and counting up. This code checks the RFC to see that it contains only digits and is less than test_limit specified in the configuration; the value in test_limit will need to be updated periodically as more RFCs are issued. An index of all RFCs is here: https://tools.ietf.org/rfc/ ]] local function rfc (options) local id = options.id; local handler = options.handler; if id:match("[^%d]") then -- if RFC has anything but digits set_message ('err_bad_rfc'); -- set an error message options.coins_list_t['RFC'] = nil; -- when error, unset so not included in COinS else -- RFC is only digits local id_num = tonumber (id); -- convert id to a number for range testing if 1 > id_num or handler.id_limit < id_num then -- if RFC is outside test limit boundaries set_message ('err_bad_rfc'); -- set an error message options.coins_list_t['RFC'] = nil; -- when error, unset so not included in COinS end end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access}); end --[[--------------------------< S 2 C I D >-------------------------------------------------------------------- Format an S2CID, do simple error checking S2CIDs are sequential numbers beginning at 1 and counting up. This code checks the S2CID to see that it is only digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically as more S2CIDs are issued. ]] local function s2cid (options) local id = options.id; local access = options.access; local handler = options.handler; local id_num; local text; id_num = id:match ('^[1-9]%d*$'); -- id must be all digits; must not begin with 0; no open access flag if is_set (id_num) then -- id_num has a value so test it id_num = tonumber (id_num); -- convert id_num to a number for range testing if handler.id_limit < id_num then -- if S2CID is outside test limit boundaries set_message ('err_bad_s2cid'); -- set an error message options.coins_list_t['S2CID'] = nil; -- when error, unset so not included in COinS end else -- when id format incorrect set_message ('err_bad_s2cid'); -- set an error message options.coins_list_t['S2CID'] = nil; -- when error, unset so not included in COinS end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}); return text; end --[[--------------------------< S B N >------------------------------------------------------------------------ 9-digit form of ISBN-10; uses same check-digit validation when SBN is prefixed with an additional '0' to make 10 digits sbn value not made part of COinS metadata because we don't have a url or isn't a COinS-defined identifier (rft.xxx) or an identifier registered at info-uri.info (info:) ]] local function sbn (options) local id = options.id; local ignore_invalid = options.accept; local handler = options.handler; local function return_result (check, err_type) -- local function to handle the various returns local SBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator}); if not ignore_invalid then -- if not ignoring SBN errors if not check then options.coins_list_t['SBN'] = nil; -- when error, unset so not included in COinS; not really necessary here because sbn not made part of COinS set_message ('err_bad_sbn', {err_type}); -- display an error message return SBN; end else set_message ('maint_isbn_ignore'); -- add a maint category even when there is no error (ToDo: Possibly switch to separate message for SBNs only) end return SBN; end if id:match ('[^%s-0-9X]') then return return_result (false, cfg.err_msg_supl.char); -- fail if SBN contains anything but digits, hyphens, or the uppercase X end local ident = id:gsub ('[%s-]', ''); -- remove hyphens and whitespace; they interfere with the rest of the tests if 9 ~= ident:len() then return return_result (false, cfg.err_msg_supl.length); -- fail if incorrect length end if ident:match ('^%d*X?$') == nil then return return_result (false, cfg.err_msg_supl.form); -- fail if SBN has 'X' anywhere but last position end return return_result (is_valid_isxn ('0' .. ident, 10), cfg.err_msg_supl.check); end --[[--------------------------< S S R N >---------------------------------------------------------------------- Format an SSRN, do simple error checking SSRNs are sequential numbers beginning at 100? and counting up. This code checks the SSRN to see that it is only digits and is greater than 99 and less than test_limit; the value in local variable test_limit will need to be updated periodically as more SSRNs are issued. ]] local function ssrn (options) local id = options.id; local handler = options.handler; local id_num; local text; id_num = id:match ('^%d+$'); -- id must be all digits if is_set (id_num) then -- id_num has a value so test it id_num = tonumber (id_num); -- convert id_num to a number for range testing if 100 > id_num or handler.id_limit < id_num then -- if SSRN is outside test limit boundaries set_message ('err_bad_ssrn'); -- set an error message options.coins_list_t['SSRN'] = nil; -- when error, unset so not included in COinS end else -- when id format incorrect set_message ('err_bad_ssrn'); -- set an error message options.coins_list_t['SSRN'] = nil; -- when error, unset so not included in COinS end text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = options.access}); return text; end --[[--------------------------< U S E N E T _ I D >------------------------------------------------------------ Validate and format a usenet message id. Simple error checking, looks for 'id-left@id-right' not enclosed in '<' and/or '>' angle brackets. ]] local function usenet_id (options) local id = options.id; local handler = options.handler; local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}) if not id:match('^.+@.+$') or not id:match('^[^<].*[^>]$') then -- doesn't have '@' or has one or first or last character is '< or '>' set_message ('err_bad_usenet_id') -- add an error message if the message id is invalid options.coins_list_t['USENETID'] = nil; -- when error, unset so not included in COinS end return text; end --[[--------------------------< Z B L >----------------------------------------------------------------------- A numerical identifier in the form nnnn.nnnnn - leading zeros in the first quartet optional format described here: http://emis.mi.sanu.ac.rs/ZMATH/zmath/en/help/search/ temporary format is apparently eight digits. Anything else is an error ]] local function zbl (options) local id = options.id; local handler = options.handler; if id:match('^%d%d%d%d%d%d%d%d$') then -- is this identifier using temporary format? set_message ('maint_zbl'); -- yes, add maint cat elseif not id:match('^%d?%d?%d?%d%.%d%d%d%d%d$') then -- not temporary, is it normal format? set_message ('err_bad_zbl'); -- no, set an error message options.coins_list_t['ZBL'] = nil; -- when error, unset so not included in COinS end return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode}); end --============================<< I N T E R F A C E F U N C T I O N S >>========================================== --[[--------------------------< E X T R A C T _ I D S >------------------------------------------------------------ Populates ID table from arguments using configuration settings. Loops through cfg.id_handlers and searches args for any of the parameters listed in each cfg.id_handlers['...'].parameters. If found, adds the parameter and value to the identifier list. Emits redundant error message if more than one alias exists in args ]] local function extract_ids (args) local id_list = {}; -- list of identifiers found in args for k, v in pairs (cfg.id_handlers) do -- k is uppercase identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table v = select_one (args, v.parameters, 'err_redundant_parameters' ); -- v.parameters is a table of aliases for k; here we pick one from args if present if is_set (v) then id_list[k] = v; end -- if found in args, add identifier to our list end return id_list; end --[[--------------------------< E X T R A C T _ I D _ A C C E S S _ L E V E L S >-------------------------------------- Fetches custom id access levels from arguments using configuration settings. Parameters which have a predefined access level (e.g. arxiv) do not use this function as they are directly rendered as free without using an additional parameter. returns a table of k/v pairs where k is same as the identifier's key in cfg.id_handlers and v is the assigned (valid) keyword access-level values must match the case used in cfg.keywords_lists['id-access'] (lowercase unless there is some special reason for something else) ]] local function extract_id_access_levels (args, id_list) local id_accesses_list = {}; for k, v in pairs (cfg.id_handlers) do local access_param = v.custom_access; -- name of identifier's access-level parameter if is_set (access_param) then local access_level = args[access_param]; -- get the assigned value if there is one if is_set (access_level) then if not in_array (access_level, cfg.keywords_lists['id-access']) then -- exact match required set_message ('err_invalid_param_val', {access_param, access_level}); access_level = nil; -- invalid so unset end if not is_set (id_list[k]) then -- identifier access-level must have a matching identifier set_message ('err_param_access_requires_param', {k:lower()}); -- parameter name is uppercase in cfg.id_handlers (k); lowercase for error message end id_accesses_list[k] = cfg.keywords_xlate[access_level]; -- get translated keyword end end end return id_accesses_list; end --[[--------------------------< B U I L D _ I D _ L I S T >---------------------------------------------------- render the identifiers into a sorted sequence table <ID_list_coins_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value <options_t> is a table of various k/v option pairs provided in the call to new_build_id_list(); modified by this function and passed to all identifier rendering functions <access_levels_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value (if valid) returns a sequence table of sorted (by hkey - 'handler' key) rendered identifier strings ]] local function build_id_list (ID_list_coins_t, options_t, access_levels_t) local ID_list_t = {}; local accept; local func_map = { --function map points to functions associated with hkey identifier ['ARXIV'] = arxiv, ['ASIN'] = asin, ['BIBCODE'] = bibcode, ['BIORXIV'] = biorxiv, ['CITESEERX'] = citeseerx, ['DOI'] = doi, ['EISSN'] = issn, ['HDL'] = hdl, ['ISBN'] = isbn, ['ISMN'] = ismn, ['ISSN'] = issn, ['JFM'] = jfm, ['JSTOR'] = jstor, ['LCCN'] = lccn, ['MR'] = mr, ['OCLC'] = oclc, ['OL'] = openlibrary, ['OSTI'] = osti, ['PMC'] = pmc, ['PMID'] = pmid, ['RFC'] = rfc, ['S2CID'] = s2cid, ['SBN'] = sbn, ['SSRN'] = ssrn, ['USENETID'] = usenet_id, ['ZBL'] = zbl, } for hkey, v in pairs (ID_list_coins_t) do v, accept = has_accept_as_written (v); -- remove accept-as-written markup if present; accept is boolean true when markup removed; false else -- every function gets the options table with value v and accept boolean options_t.hkey = hkey; -- ~/Configuration handler key options_t.id = v; -- add that identifier value to the options table options_t.accept = accept; -- add the accept boolean flag options_t.access = access_levels_t[hkey]; -- add the access level for those that have an |<identifier-access= parameter options_t.handler = cfg.id_handlers[hkey]; options_t.coins_list_t = ID_list_coins_t; -- pointer to ID_list_coins_t; for |asin= and |ol=; also to keep erroneous values out of the citation's metadata options_t.coins_list_t[hkey] = v; -- id value without accept-as-written markup for metadata if options_t.handler.access and not in_array (options_t.handler.access, cfg.keywords_lists['id-access']) then error (cfg.messages['unknown_ID_access'] .. options_t.handler.access); -- here when handler access key set to a value not listed in list of allowed id access keywords end if func_map[hkey] then local id_text = func_map[hkey] (options_t); -- call the function to get identifier text and any error message table.insert (ID_list_t, {hkey, id_text}); -- add identifier text to the output sequence table else error (cfg.messages['unknown_ID_key'] .. hkey); -- here when func_map doesn't have a function for hkey end end local function comp (a, b) -- used by following table.sort() return a[1]:lower() < b[1]:lower(); -- sort by hkey end table.sort (ID_list_t, comp); -- sequence table of tables sort for k, v in ipairs (ID_list_t) do -- convert sequence table of tables to simple sequence table of strings ID_list_t[k] = v[2]; -- v[2] is the identifier rendering from the call to the various functions in func_map{} end return ID_list_t; end --[[--------------------------< O P T I O N S _ C H E C K >---------------------------------------------------- check that certain option parameters have their associated identifier parameters with values <ID_list_coins_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value <ID_support_t> is a sequence table of tables created in citation0() where each subtable has four elements: [1] is the support parameter's assigned value; empty string if not set [2] is a text string same as key in cfg.id_handlers [3] is cfg.error_conditions key used to create error message [4] is original ID support parameter name used to create error message returns nothing; on error emits an appropriate error message ]] local function options_check (ID_list_coins_t, ID_support_t) for _, v in ipairs (ID_support_t) do if is_set (v[1]) and not ID_list_coins_t[v[2]] then -- when support parameter has a value but matching identifier parameter is missing or empty set_message (v[3], (v[4])); -- emit the appropriate error message end end end --[[--------------------------< I D E N T I F I E R _ L I S T S _ G E T >-------------------------------------- Creates two identifier lists: a k/v table of identifiers and their values to be used locally and for use in the COinS metadata, and a sequence table of the rendered identifier strings that will be included in the rendered citation. ]] local function identifier_lists_get (args_t, options_t, ID_support_t) local ID_list_coins_t = extract_ids (args_t); -- get a table of identifiers and their values for use locally and for use in COinS options_check (ID_list_coins_t, ID_support_t); -- ID support parameters must have matching identifier parameters local ID_access_levels_t = extract_id_access_levels (args_t, ID_list_coins_t); -- get a table of identifier access levels local ID_list_t = build_id_list (ID_list_coins_t, options_t, ID_access_levels_t); -- get a sequence table of rendered identifier strings return ID_list_t, ID_list_coins_t; -- return the tables end --[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >-------------------------------------- Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules. ]] local function set_selected_modules (cfg_table_ptr, utilities_page_ptr) cfg = cfg_table_ptr; has_accept_as_written = utilities_page_ptr.has_accept_as_written; -- import functions from select Module:Citation/CS1/Utilities module is_set = utilities_page_ptr.is_set; in_array = utilities_page_ptr.in_array; set_message = utilities_page_ptr.set_message; select_one = utilities_page_ptr.select_one; substitute = utilities_page_ptr.substitute; make_wikilink = utilities_page_ptr.make_wikilink; z = utilities_page_ptr.z; -- table of tables in Module:Citation/CS1/Utilities end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { auto_link_urls = auto_link_urls, -- table of identifier URLs to be used when auto-linking |title= identifier_lists_get = identifier_lists_get, -- experiment to replace individual calls to build_id_list(), extract_ids, extract_id_access_levels is_embargoed = is_embargoed; set_selected_modules = set_selected_modules; } 0f40bcba575710f5da9e7d29a8305288fbb30ac4 Module:Citation/CS1/COinS 828 56 128 127 2022-09-04T15:24:37Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local has_accept_as_written, is_set, in_array, remove_wiki_link, strip_apostrophe_markup; -- functions in Module:Citation/CS1/Utilities local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration --[[--------------------------< M A K E _ C O I N S _ T I T L E >---------------------------------------------- Makes a title for COinS from Title and / or ScriptTitle (or any other name-script pairs) Apostrophe markup (bold, italics) is stripped from each value so that the COinS metadata isn't corrupted with strings of %27%27... ]] local function make_coins_title (title, script) title = has_accept_as_written (title); if is_set (title) then title = strip_apostrophe_markup (title); -- strip any apostrophe markup else title = ''; -- if not set, make sure title is an empty string end if is_set (script) then script = script:gsub ('^%l%l%s*:%s*', ''); -- remove language prefix if present (script value may now be empty string) script = strip_apostrophe_markup (script); -- strip any apostrophe markup else script = ''; -- if not set, make sure script is an empty string end if is_set (title) and is_set (script) then script = ' ' .. script; -- add a space before we concatenate end return title .. script; -- return the concatenation end --[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >---------------------------------- Returns a string where all of Lua's magic characters have been escaped. This is important because functions like string.gsub() treat their pattern and replace strings as patterns, not literal strings. ]] local function escape_lua_magic_chars (argument) argument = argument:gsub("%%", "%%%%"); -- replace % with %% argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other Lua magic pattern characters return argument; end --[[--------------------------< G E T _ C O I N S _ P A G E S >------------------------------------------------ Extract page numbers from external wikilinks in any of the |page=, |pages=, or |at= parameters for use in COinS. ]] local function get_coins_pages (pages) local pattern; if not is_set (pages) then return pages; end -- if no page numbers then we're done while true do pattern = pages:match("%[(%w*:?//[^ ]+%s+)[%w%d].*%]"); -- pattern is the opening bracket, the URL and following space(s): "[url " if nil == pattern then break; end -- no more URLs pattern = escape_lua_magic_chars (pattern); -- pattern is not a literal string; escape Lua's magic pattern characters pages = pages:gsub(pattern, ""); -- remove as many instances of pattern as possible end pages = pages:gsub("[%[%]]", ""); -- remove the brackets pages = pages:gsub("–", "-" ); -- replace endashes with hyphens pages = pages:gsub("&%w+;", "-" ); -- and replace HTML entities (&ndash; etc.) with hyphens; do we need to replace numerical entities like &#32; and the like? return pages; end --[=[-------------------------< C O I N S _ R E P L A C E _ M A T H _ S T R I P M A R K E R >------------------ There are three options for math markup rendering that depend on the editor's math preference settings. These settings are at [[Special:Preferences#mw-prefsection-rendering]] and are PNG images TeX source MathML with SVG or PNG fallback All three are heavy with HTML and CSS which doesn't belong in the metadata. Without this function, the metadata saved in the raw wikitext contained the rendering determined by the settings of the last editor to save the page. This function gets the rendered form of an equation according to the editor's preference before the page is saved. It then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so that the page is saved without extraneous HTML/CSS markup and with a reasonably readable text form of the equation. When a replacement is made, this function returns true and the value with replacement; otherwise false and the initial value. To replace multipe equations it is necessary to call this function from within a loop. ]=] local function coins_replace_math_stripmarker (value) local stripmarker = cfg.stripmarkers['math']; local rendering = value:match (stripmarker); -- is there a math stripmarker if not rendering then -- when value doesn't have a math stripmarker, abandon this test return false, value; end rendering = mw.text.unstripNoWiki (rendering); -- convert stripmarker into rendered value (or nil? ''? when math render error) if rendering:match ('alt="[^"]+"') then -- if PNG math option rendering = rendering:match ('alt="([^"]+)"'); -- extract just the math text elseif rendering:match ('$%s+.+%s+%$') then -- if TeX math option; $ is legit character that is escapes as \$ rendering = rendering:match ('$%s+(.+)%s+%$') -- extract just the math text elseif rendering:match ('<annotation[^>]+>.+</annotation>') then -- if MathML math option rendering = rendering:match ('<annotation[^>]+>(.+)</annotation>') -- extract just the math text else return false, value; -- had math stripmarker but not one of the three defined forms end return true, value:gsub (stripmarker, rendering, 1); end --[[--------------------------< C O I N S _ C L E A N U P >---------------------------------------------------- Cleanup parameter values for the metadata by removing or replacing invisible characters and certain HTML entities. 2015-12-10: there is a bug in mw.text.unstripNoWiki (). It replaces math stripmarkers with the appropriate content when it shouldn't. See https://phabricator.wikimedia.org/T121085 and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29 TODO: move the replacement patterns and replacement values into a table in /Configuration similar to the invisible characters table? ]] local function coins_cleanup (value) local replaced = true; -- default state to get the do loop running while replaced do -- loop until all math stripmarkers replaced replaced, value = coins_replace_math_stripmarker (value); -- replace math stripmarker with text representation of the equation end value = value:gsub (cfg.stripmarkers['math'], "MATH RENDER ERROR"); -- one or more couldn't be replaced; insert vague error message value = mw.text.unstripNoWiki (value); -- replace nowiki stripmarkers with their content value = value:gsub ('<span class="nowrap" style="padding%-left:0%.1em;">&#39;(s?)</span>', "'%1"); -- replace {{'}} or {{'s}} with simple apostrophe or apostrophe-s value = value:gsub ('&nbsp;', ' '); -- replace &nbsp; entity with plain space value = value:gsub ('\226\128\138', ' '); -- replace hair space with plain space if not mw.ustring.find (value, cfg.indic_script) then -- don't remove zero-width joiner characters from indic script value = value:gsub ('&zwj;', ''); -- remove &zwj; entities value = mw.ustring.gsub (value, '[\226\128\141\226\128\139\194\173]', ''); -- remove zero-width joiner, zero-width space, soft hyphen end value = value:gsub ('[\009\010\013 ]+', ' '); -- replace horizontal tab, line feed, carriage return with plain space return value; end --[[--------------------------< C O I N S >-------------------------------------------------------------------- COinS metadata (see <http://ocoins.info/>) allows automated tools to parse the citation information. ]] local function COinS(data, class) if 'table' ~= type(data) or nil == next(data) then return ''; end for k, v in pairs (data) do -- spin through all of the metadata parameter values if 'ID_list' ~= k and 'Authors' ~= k then -- except the ID_list and Author tables (author nowiki stripmarker done when Author table processed) data[k] = coins_cleanup (v); end end local ctx_ver = "Z39.88-2004"; -- treat table strictly as an array with only set values. local OCinSoutput = setmetatable( {}, { __newindex = function(self, key, value) if is_set(value) then rawset( self, #self+1, table.concat{ key, '=', mw.uri.encode( remove_wiki_link( value ) ) } ); end end }); if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn', 'journal', 'news', 'magazine'}) or (in_array (class, {'conference', 'interview', 'map', 'press release', 'web'}) and is_set(data.Periodical)) or ('citation' == class and is_set(data.Periodical) and not is_set (data.Encyclopedia)) then OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"; -- journal metadata identifier if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) then -- set genre according to the type of citation template we are rendering OCinSoutput["rft.genre"] = "preprint"; -- cite arxiv, cite biorxiv, cite citeseerx, cite ssrn elseif 'conference' == class then OCinSoutput["rft.genre"] = "conference"; -- cite conference (when Periodical set) elseif 'web' == class then OCinSoutput["rft.genre"] = "unknown"; -- cite web (when Periodical set) else OCinSoutput["rft.genre"] = "article"; -- journal and other 'periodical' articles end OCinSoutput["rft.jtitle"] = data.Periodical; -- journal only OCinSoutput["rft.atitle"] = data.Title; -- 'periodical' article titles -- these used only for periodicals OCinSoutput["rft.ssn"] = data.Season; -- keywords: winter, spring, summer, fall OCinSoutput["rft.quarter"] = data.Quarter; -- single digits 1->first quarter, etc. OCinSoutput["rft.chron"] = data.Chron; -- free-form date components OCinSoutput["rft.volume"] = data.Volume; -- does not apply to books OCinSoutput["rft.issue"] = data.Issue; OCinSoutput["rft.pages"] = data.Pages; -- also used in book metadata elseif 'thesis' ~= class then -- all others except cite thesis are treated as 'book' metadata; genre distinguishes OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; -- book metadata identifier if 'report' == class or 'techreport' == class then -- cite report and cite techreport OCinSoutput["rft.genre"] = "report"; elseif 'conference' == class then -- cite conference when Periodical not set OCinSoutput["rft.genre"] = "conference"; OCinSoutput["rft.atitle"] = data.Chapter; -- conference paper as chapter in proceedings (book) elseif in_array (class, {'book', 'citation', 'encyclopaedia', 'interview', 'map'}) then if is_set (data.Chapter) then OCinSoutput["rft.genre"] = "bookitem"; OCinSoutput["rft.atitle"] = data.Chapter; -- book chapter, encyclopedia article, interview in a book, or map title else if 'map' == class or 'interview' == class then OCinSoutput["rft.genre"] = 'unknown'; -- standalone map or interview else OCinSoutput["rft.genre"] = 'book'; -- book and encyclopedia end end else -- {'audio-visual', 'AV-media-notes', 'DVD-notes', 'episode', 'interview', 'mailinglist', 'map', 'newsgroup', 'podcast', 'press release', 'serial', 'sign', 'speech', 'web'} OCinSoutput["rft.genre"] = "unknown"; end OCinSoutput["rft.btitle"] = data.Title; -- book only OCinSoutput["rft.place"] = data.PublicationPlace; -- book only OCinSoutput["rft.series"] = data.Series; -- book only OCinSoutput["rft.pages"] = data.Pages; -- book, journal OCinSoutput["rft.edition"] = data.Edition; -- book only OCinSoutput["rft.pub"] = data.PublisherName; -- book and dissertation else -- cite thesis OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:dissertation"; -- dissertation metadata identifier OCinSoutput["rft.title"] = data.Title; -- dissertation (also patent but that is not yet supported) OCinSoutput["rft.degree"] = data.Degree; -- dissertation only OCinSoutput['rft.inst'] = data.PublisherName; -- book and dissertation end -- NB. Not currently supported are "info:ofi/fmt:kev:mtx:patent", "info:ofi/fmt:kev:mtx:dc", "info:ofi/fmt:kev:mtx:sch_svc", "info:ofi/fmt:kev:mtx:ctx" -- and now common parameters (as much as possible) OCinSoutput["rft.date"] = data.Date; -- book, journal, dissertation for k, v in pairs( data.ID_list ) do -- what to do about these? For now assume that they are common to all? if k == 'ISBN' then v = v:gsub( "[^-0-9X]", "" ); end local id = cfg.id_handlers[k].COinS; if string.sub( id or "", 1, 4 ) == 'info' then -- for ids that are in the info:registry OCinSoutput["rft_id"] = table.concat{ id, "/", v }; elseif string.sub (id or "", 1, 3 ) == 'rft' then -- for isbn, issn, eissn, etc. that have defined COinS keywords OCinSoutput[ id ] = v; elseif 'url' == id then -- for urls that are assembled in ~/Identifiers; |asin= and |ol= OCinSoutput["rft_id"] = table.concat ({data.ID_list[k], "#id-name=", cfg.id_handlers[k].label}); elseif id then -- when cfg.id_handlers[k].COinS is not nil so urls created here OCinSoutput["rft_id"] = table.concat{ cfg.id_handlers[k].prefix, v, cfg.id_handlers[k].suffix or '', "#id-name=", cfg.id_handlers[k].label }; -- others; provide a URL and indicate identifier name as #fragment (human-readable, but transparent to browsers) end end local last, first; for k, v in ipairs( data.Authors ) do last, first = coins_cleanup (v.last), coins_cleanup (v.first or ''); -- replace any nowiki stripmarkers, non-printing or invisible characters if k == 1 then -- for the first author name only if is_set(last) and is_set(first) then -- set these COinS values if |first= and |last= specify the first author name OCinSoutput["rft.aulast"] = last; -- book, journal, dissertation OCinSoutput["rft.aufirst"] = first; -- book, journal, dissertation elseif is_set(last) then OCinSoutput["rft.au"] = last; -- book, journal, dissertation -- otherwise use this form for the first name end else -- for all other authors if is_set(last) and is_set(first) then OCinSoutput["rft.au"] = table.concat{ last, ", ", first }; -- book, journal, dissertation elseif is_set(last) then OCinSoutput["rft.au"] = last; -- book, journal, dissertation end -- TODO: At present we do not report "et al.". Add anything special if this condition applies? end end OCinSoutput.rft_id = data.URL; OCinSoutput.rfr_id = table.concat{ "info:sid/", mw.site.server:match( "[^/]*$" ), ":", data.RawPage }; -- TODO: Add optional extra info: -- rfr_dat=#REVISION<version> (referrer private data) -- ctx_id=<data.RawPage>#<ref> (identifier for the context object) -- ctx_tim=<ts> (timestamp in format yyyy-mm-ddThh:mm:ssTZD or yyyy-mm-dd) -- ctx_enc=info:ofi/enc:UTF-8 (character encoding) OCinSoutput = setmetatable( OCinSoutput, nil ); -- sort with version string always first, and combine. -- table.sort( OCinSoutput ); table.insert( OCinSoutput, 1, "ctx_ver=" .. ctx_ver ); -- such as "Z39.88-2004" return table.concat(OCinSoutput, "&"); end --[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >-------------------------------------- Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules. ]] local function set_selected_modules (cfg_table_ptr, utilities_page_ptr) cfg = cfg_table_ptr; has_accept_as_written = utilities_page_ptr.has_accept_as_written; -- import functions from selected Module:Citation/CS1/Utilities module is_set = utilities_page_ptr.is_set; in_array = utilities_page_ptr.in_array; remove_wiki_link = utilities_page_ptr.remove_wiki_link; strip_apostrophe_markup = utilities_page_ptr.strip_apostrophe_markup; end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { make_coins_title = make_coins_title, get_coins_pages = get_coins_pages, COinS = COinS, set_selected_modules = set_selected_modules, } 54a5c6fce3535cf48f207524439635ed96505a13 Module:Citation/CS1/styles.css 828 57 130 129 2022-09-04T15:24:38Z SpaceMan 2 1 revision imported: Canopus text text/plain /* Protection icon the following line controls the page-protection icon in the upper right corner it must remain within this comment {{sandbox other||{{pp-template}}}} */ /* Overrides Some wikis do not override user agent default styles for HTML <cite> and <q>, unlike en.wp. On en.wp, keep these the same as [[MediaWiki:Common.css]]. The word-wrap and :target styles were moved here from Common.css. On en.wp, keep these the same as [[Template:Citation/styles.css]]. */ cite.citation { font-style: inherit; /* Remove italics for <cite> */ /* Break long urls, etc., rather than overflowing box */ word-wrap: break-word; } .citation q { quotes: '"' '"' "'" "'"; /* Straight quote marks for <q> */ } /* Highlight linked elements (such as clicked references) in blue */ .citation:target { /* ignore the linter - all browsers of interest implement this */ background-color: rgba(0, 127, 255, 0.133); } /* ID and URL access Both core and Common.css have selector .mw-parser-output a[href$=".pdf"].external for PDF pages. All TemplateStyles pages are hoisted to .mw-parser-output. We need to have specificity equal to a[href$=".pdf"].external for locks to override PDF icon. That's essentially 2 classes and 1 element. the .id-lock-... selectors are for use by non-citation templates like {{Catalog lookup link}} which do not have to handle PDF links */ .id-lock-free a, .citation .cs1-lock-free a { background: linear-gradient(transparent, transparent), url(//upload.wikimedia.org/wikipedia/commons/6/65/Lock-green.svg) right 0.1em center/9px no-repeat; } .id-lock-limited a, .id-lock-registration a, .citation .cs1-lock-limited a, .citation .cs1-lock-registration a { background: linear-gradient(transparent, transparent), url(//upload.wikimedia.org/wikipedia/commons/d/d6/Lock-gray-alt-2.svg) right 0.1em center/9px no-repeat; } .id-lock-subscription a, .citation .cs1-lock-subscription a { background: linear-gradient(transparent, transparent), url(//upload.wikimedia.org/wikipedia/commons/a/aa/Lock-red-alt-2.svg) right 0.1em center/9px no-repeat; } /* Wikisource Wikisource icon when |chapter= or |title= is wikilinked to Wikisource as in cite wikisource */ .cs1-ws-icon a { background: linear-gradient(transparent, transparent), url(//upload.wikimedia.org/wikipedia/commons/4/4c/Wikisource-logo.svg) right 0.1em center/12px no-repeat; } /* Errors and maintenance */ .cs1-code { /* <code>...</code> style override: mediawiki's css definition is specified here: https://git.wikimedia.org/blob/mediawiki%2Fcore.git/ 69cd73811f7aadd093050dbf20ed70ef0b42a713/skins%2Fcommon%2FcommonElements.css#L199 */ color: inherit; background: inherit; border: none; padding: inherit; } .cs1-hidden-error { display: none; color: #d33; } .cs1-visible-error { color: #d33; } .cs1-maint { display: none; color: #3a3; margin-left: 0.3em; } /* Small text size Set small text size in one place. 0.95 (here) * 0.9 (from references list) is ~0.85, which is the lower bound for size for accessibility. Old styling for this was just 0.85. We could write the rule so that when this template is inside references/reflist, only then does it multiply by 0.95; else multiply by 0.85 */ .cs1-format { font-size: 95%; } /* kerning */ .cs1-kern-left { padding-left: 0.2em; } .cs1-kern-right { padding-right: 0.2em; } /* selflinks – avoid bold font style when cs1|2 template links to the current page */ .citation .mw-selflink { font-weight: inherit; } 016143e761e7a41b22296023b6119ee97303dabb Template:Pagetype 10 58 132 131 2022-09-04T15:24:39Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{<includeonly>safesubst:</includeonly>#invoke:pagetype|main}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> b8e6aa66678cd57877ea2c607372a45070f030a7 Module:Pagetype 828 59 134 133 2022-09-04T15:24:39Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- -- -- PAGETYPE -- -- -- -- This is a meta-module intended to replace {{pagetype}} and similar -- -- templates. It automatically detects namespaces, and allows for a -- -- great deal of customisation. It can easily be ported to other -- -- wikis by changing the values in the [[Module:Pagetype/config]]. -- -- -- -------------------------------------------------------------------------------- -- Load config. local cfg = mw.loadData('Module:Pagetype/config') -- Load required modules. local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') local nsDetectModule = require('Module:Namespace detect') local nsDetect = nsDetectModule._main local getParamMappings = nsDetectModule.getParamMappings local getPageObject = nsDetectModule.getPageObject local p = {} local function shallowCopy(t) -- Makes a shallow copy of a table. local ret = {} for k, v in pairs(t) do ret[k] = v end return ret end local function checkPagetypeInput(namespace, val) -- Checks to see whether we need the default value for the given namespace, -- and if so gets it from the pagetypes table. -- The yesno function returns true/false for "yes", "no", etc., and returns -- val for other input. local ret = yesno(val, val) if ret and type(ret) ~= 'string' then ret = cfg.pagetypes[namespace] end return ret end local function getPagetypeFromClass(class, param, aliasTable, default) -- Gets the pagetype from a class specified from the first positional -- parameter. param = yesno(param, param) if param ~= false then -- No check if specifically disallowed. for _, alias in ipairs(aliasTable) do if class == alias then if type(param) == 'string' then return param else return default end end end end end local function getNsDetectValue(args) -- Builds the arguments to pass to [[Module:Namespace detect]] and returns -- the result. -- Get the default values. local ndArgs = {} local defaultns = args[cfg.defaultns] if defaultns == cfg.defaultnsAll then ndArgs = shallowCopy(cfg.pagetypes) else local defaultnsArray if defaultns == cfg.defaultnsExtended then defaultnsArray = cfg.extendedNamespaces elseif defaultns == cfg.defaultnsNone then defaultnsArray = {} else defaultnsArray = cfg.defaultNamespaces end for _, namespace in ipairs(defaultnsArray) do ndArgs[namespace] = cfg.pagetypes[namespace] end end --[[ -- Add custom values passed in from the arguments. These overwrite the -- defaults. The possible argument names are fetched from -- Module:Namespace detect automatically in case new namespaces are -- added. Although we accept namespace aliases as parameters, we only pass -- the local namespace name as a parameter to Module:Namespace detect. -- This means that the "image" parameter can overwrite defaults for the -- File: namespace, which wouldn't work if we passed the parameters through -- separately. --]] local mappings = getParamMappings() for ns, paramAliases in pairs(mappings) do -- Copy the aliases table, as # doesn't work with tables returned from -- mw.loadData. paramAliases = shallowCopy(paramAliases) local paramName = paramAliases[1] -- Iterate backwards along the array so that any values for the local -- namespace names overwrite those for namespace aliases. for i = #paramAliases, 1, -1 do local paramAlias = paramAliases[i] local ndArg = checkPagetypeInput(paramAlias, args[paramAlias]) if ndArg == false then -- If any arguments are false, convert them to nil to protect -- against breakage by future changes to -- [[Module:Namespace detect]]. ndArgs[paramName] = nil elseif ndArg then ndArgs[paramName] = ndArg end end end -- Check for disambiguation-class and N/A-class pages in mainspace. if ndArgs.main then local class = args[1] if type(class) == 'string' then -- Put in lower case so e.g. "Dab" and "dab" will both match. class = mw.ustring.lower(class) end local dab = getPagetypeFromClass( class, args[cfg.dab], cfg.dabAliases, cfg.dabDefault ) if dab then ndArgs.main = dab else local na = getPagetypeFromClass( class, args[cfg.na], cfg.naAliases, cfg.naDefault ) if na then ndArgs.main = na end end end -- If there is no talk value specified, use the corresponding subject -- namespace for talk pages. if not ndArgs.talk then ndArgs.subjectns = true end -- Add the fallback value. This can also be customised, but it cannot be -- disabled. local other = args[cfg.other] -- We will ignore true/false/nil results from yesno here, but using it -- anyway for consistency. other = yesno(other, other) if type(other) == 'string' then ndArgs.other = other else ndArgs.other = cfg.otherDefault end -- Allow custom page values. ndArgs.page = args.page return nsDetect(ndArgs) end local function detectRedirects(args) local redirect = args[cfg.redirect] -- The yesno function returns true/false for "yes", "no", etc., and returns -- redirect for other input. redirect = yesno(redirect, redirect) if redirect == false then -- Detect redirects unless they have been explicitly disallowed with -- "redirect=no" or similar. return end local pageObject = getPageObject(args.page) -- If we are using subject namespaces elsewhere, do so here as well. if pageObject and not yesno(args.talk, true) and args[cfg.defaultns] ~= cfg.defaultnsAll then pageObject = getPageObject( pageObject.subjectNsText .. ':' .. pageObject.text ) end -- Allow custom values for redirects. if pageObject and pageObject.isRedirect then if type(redirect) == 'string' then return redirect else return cfg.redirectDefault end end end function p._main(args) local redirect = detectRedirects(args) local pagetype = "" if redirect then pagetype = redirect else pagetype = getNsDetectValue(args) end if yesno(args.plural, false) then if cfg.irregularPlurals[pagetype] then pagetype = cfg.irregularPlurals[pagetype] else pagetype = pagetype .. cfg.plural -- often 's' end end if yesno(args.caps, false) then pagetype = mw.ustring.upper(mw.ustring.sub(pagetype, 1, 1)) .. mw.ustring.sub(pagetype, 2) end return pagetype end function p.main(frame) local args = getArgs(frame) return p._main(args) end return p 210524e0c60e3354325aea88c508e94423ad228d Module:Pagetype/config 828 60 136 135 2022-09-04T15:24:40Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- Module:Pagetype configuration data -- -- This page holds localisation and configuration data for Module:Pagetype. -- -------------------------------------------------------------------------------- local cfg = {} -- Don't edit this line. -------------------------------------------------------------------------------- -- Start configuration data -- -------------------------------------------------------------------------------- -- This table holds the values to use for "main=true", "user=true", etc. Keys to -- this table should be namespace parameters that can be used with -- [[Module:Namespace detect]]. cfg.pagetypes = { ['main'] = 'article', ['user'] = 'user page', ['project'] = 'project page', ['wikipedia'] = 'project page', ['wp'] = 'project page', ['file'] = 'file', ['image'] = 'file', ['mediawiki'] = 'interface page', ['template'] = 'template', ['help'] = 'help page', ['category'] = 'category', ['portal'] = 'portal', ['draft'] = 'draft', ['timedtext'] = 'Timed Text page', ['module'] = 'module', ['topic'] = 'topic', ['gadget'] = 'gadget', ['gadget definition'] = 'gadget definition', ['talk'] = 'talk page', ['special'] = 'special page', ['media'] = 'file', } -- This table holds the names of the namespaces to be looked up from -- cfg.pagetypes by default. cfg.defaultNamespaces = { 'main', 'file', 'template', 'category', 'module' } -- This table holds the names of the namespaces to be looked up from -- cfg.pagetypes if cfg.defaultnsExtended is set. cfg.extendedNamespaces = { 'main', 'user', 'project', 'file', 'mediawiki', 'template', 'category', 'help', 'portal', 'module', 'draft' } -- The parameter name to set which default namespace values to be looked up from -- cfg.pagetypes. cfg.defaultns = 'defaultns' -- The value of cfg.defaultns to set all namespaces, including talk. cfg.defaultnsAll = 'all' -- The value of cfg.defaultns to set the namespaces listed in -- cfg.extendedNamespaces cfg.defaultnsExtended = 'extended' -- The value of cfg.defaultns to set no default namespaces. cfg.defaultnsNone = 'none' -- The parameter name to use for disambiguation pages page. cfg.dab = 'dab' -- This table holds the different possible aliases for disambiguation-class -- pages. These should be lower-case. cfg.dabAliases = { 'disambiguation', 'disambig', 'disamb', 'dab' } -- The default value for disambiguation pages. cfg.dabDefault = 'page' -- The parameter name to use for N/A-class page. cfg.na = 'na' -- This table holds the different possible aliases for N/A-class pages. These -- should be lower-case. cfg.naAliases = {'na', 'n/a'} -- The default value for N/A-class pages. cfg.naDefault = 'page' -- The parameter name to use for redirects. cfg.redirect = 'redirect' -- The default value to use for redirects. cfg.redirectDefault = 'redirect' -- The parameter name for undefined namespaces. cfg.other = 'other' -- The value used if the module detects an undefined namespace. cfg.otherDefault = 'page' -- The usual suffix denoting a plural. cfg.plural = 's' -- This table holds plurals not formed by a simple suffix. cfg.irregularPlurals = { ["category"] = "categories" } -------------------------------------------------------------------------------- -- End configuration data -- -------------------------------------------------------------------------------- return cfg -- Don't edit this line e2eb36d6c43611a422bae37947ebeb04b695dcba Module:Namespace detect 828 61 138 137 2022-09-04T15:24:41Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[ -------------------------------------------------------------------------------- -- -- -- NAMESPACE DETECT -- -- -- -- This module implements the {{namespace detect}} template in Lua, with a -- -- few improvements: all namespaces and all namespace aliases are supported, -- -- and namespace names are detected automatically for the local wiki. The -- -- module can also use the corresponding subject namespace value if it is -- -- used on a talk page. Parameter names can be configured for different wikis -- -- by altering the values in the "cfg" table in -- -- Module:Namespace detect/config. -- -- -- -------------------------------------------------------------------------------- --]] local data = mw.loadData('Module:Namespace detect/data') local argKeys = data.argKeys local cfg = data.cfg local mappings = data.mappings local yesno = require('Module:Yesno') local mArguments -- Lazily initialise Module:Arguments local mTableTools -- Lazily initilalise Module:TableTools local ustringLower = mw.ustring.lower local p = {} local function fetchValue(t1, t2) -- Fetches a value from the table t1 for the first key in array t2 where -- a non-nil value of t1 exists. for i, key in ipairs(t2) do local value = t1[key] if value ~= nil then return value end end return nil end local function equalsArrayValue(t, value) -- Returns true if value equals a value in the array t. Otherwise -- returns false. for i, arrayValue in ipairs(t) do if value == arrayValue then return true end end return false end function p.getPageObject(page) -- Get the page object, passing the function through pcall in case of -- errors, e.g. being over the expensive function count limit. if page then local success, pageObject = pcall(mw.title.new, page) if success then return pageObject else return nil end else return mw.title.getCurrentTitle() end end -- Provided for backward compatibility with other modules function p.getParamMappings() return mappings end local function getNamespace(args) -- This function gets the namespace name from the page object. local page = fetchValue(args, argKeys.demopage) if page == '' then page = nil end local demospace = fetchValue(args, argKeys.demospace) if demospace == '' then demospace = nil end local subjectns = fetchValue(args, argKeys.subjectns) local ret if demospace then -- Handle "demospace = main" properly. if equalsArrayValue(argKeys.main, ustringLower(demospace)) then ret = mw.site.namespaces[0].name else ret = demospace end else local pageObject = p.getPageObject(page) if pageObject then if pageObject.isTalkPage then -- Get the subject namespace if the option is set, -- otherwise use "talk". if yesno(subjectns) then ret = mw.site.namespaces[pageObject.namespace].subject.name else ret = 'talk' end else ret = pageObject.nsText end else return nil -- return nil if the page object doesn't exist. end end ret = ret:gsub('_', ' ') return ustringLower(ret) end function p._main(args) -- Check the parameters stored in the mappings table for any matches. local namespace = getNamespace(args) or 'other' -- "other" avoids nil table keys local params = mappings[namespace] or {} local ret = fetchValue(args, params) --[[ -- If there were no matches, return parameters for other namespaces. -- This happens if there was no text specified for the namespace that -- was detected or if the demospace parameter is not a valid -- namespace. Note that the parameter for the detected namespace must be -- completely absent for this to happen, not merely blank. --]] if ret == nil then ret = fetchValue(args, argKeys.other) end return ret end function p.main(frame) mArguments = require('Module:Arguments') local args = mArguments.getArgs(frame, {removeBlanks = false}) local ret = p._main(args) return ret or '' end function p.table(frame) --[[ -- Create a wikitable of all subject namespace parameters, for -- documentation purposes. The talk parameter is optional, in case it -- needs to be excluded in the documentation. --]] -- Load modules and initialise variables. mTableTools = require('Module:TableTools') local namespaces = mw.site.namespaces local cfg = data.cfg local useTalk = type(frame) == 'table' and type(frame.args) == 'table' and yesno(frame.args.talk) -- Whether to use the talk parameter. -- Get the header names. local function checkValue(value, default) if type(value) == 'string' then return value else return default end end local nsHeader = checkValue(cfg.wikitableNamespaceHeader, 'Namespace') local aliasesHeader = checkValue(cfg.wikitableAliasesHeader, 'Aliases') -- Put the namespaces in order. local mappingsOrdered = {} for nsname, params in pairs(mappings) do if useTalk or nsname ~= 'talk' then local nsid = namespaces[nsname].id -- Add 1, as the array must start with 1; nsid 0 would be lost otherwise. nsid = nsid + 1 mappingsOrdered[nsid] = params end end mappingsOrdered = mTableTools.compressSparseArray(mappingsOrdered) -- Build the table. local ret = '{| class="wikitable"' .. '\n|-' .. '\n! ' .. nsHeader .. '\n! ' .. aliasesHeader for i, params in ipairs(mappingsOrdered) do for j, param in ipairs(params) do if j == 1 then ret = ret .. '\n|-' .. '\n| <code>' .. param .. '</code>' .. '\n| ' elseif j == 2 then ret = ret .. '<code>' .. param .. '</code>' else ret = ret .. ', <code>' .. param .. '</code>' end end end ret = ret .. '\n|-' .. '\n|}' return ret end return p a4757000273064f151f0f22dc0e139092e5ff443 Module:Namespace detect/data 828 62 140 139 2022-09-04T15:24:41Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- Namespace detect data -- -- This module holds data for [[Module:Namespace detect]] to be loaded per -- -- page, rather than per #invoke, for performance reasons. -- -------------------------------------------------------------------------------- local cfg = require('Module:Namespace detect/config') local function addKey(t, key, defaultKey) if key ~= defaultKey then t[#t + 1] = key end end -- Get a table of parameters to query for each default parameter name. -- This allows wikis to customise parameter names in the cfg table while -- ensuring that default parameter names will always work. The cfg table -- values can be added as a string, or as an array of strings. local defaultKeys = { 'main', 'talk', 'other', 'subjectns', 'demospace', 'demopage' } local argKeys = {} for i, defaultKey in ipairs(defaultKeys) do argKeys[defaultKey] = {defaultKey} end for defaultKey, t in pairs(argKeys) do local cfgValue = cfg[defaultKey] local cfgValueType = type(cfgValue) if cfgValueType == 'string' then addKey(t, cfgValue, defaultKey) elseif cfgValueType == 'table' then for i, key in ipairs(cfgValue) do addKey(t, key, defaultKey) end end cfg[defaultKey] = nil -- Free the cfg value as we don't need it any more. end local function getParamMappings() --[[ -- Returns a table of how parameter names map to namespace names. The keys -- are the actual namespace names, in lower case, and the values are the -- possible parameter names for that namespace, also in lower case. The -- table entries are structured like this: -- { -- [''] = {'main'}, -- ['wikipedia'] = {'wikipedia', 'project', 'wp'}, -- ... -- } --]] local mappings = {} local mainNsName = mw.site.subjectNamespaces[0].name mainNsName = mw.ustring.lower(mainNsName) mappings[mainNsName] = mw.clone(argKeys.main) mappings['talk'] = mw.clone(argKeys.talk) for nsid, ns in pairs(mw.site.subjectNamespaces) do if nsid ~= 0 then -- Exclude main namespace. local nsname = mw.ustring.lower(ns.name) local canonicalName = mw.ustring.lower(ns.canonicalName) mappings[nsname] = {nsname} if canonicalName ~= nsname then table.insert(mappings[nsname], canonicalName) end for _, alias in ipairs(ns.aliases) do table.insert(mappings[nsname], mw.ustring.lower(alias)) end end end return mappings end return { argKeys = argKeys, cfg = cfg, mappings = getParamMappings() } d224f42a258bc308ef3ad8cc8686cd7a4f47d005 Module:Namespace detect/config 828 63 142 141 2022-09-04T15:24:42Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- Namespace detect configuration data -- -- -- -- This module stores configuration data for Module:Namespace detect. Here -- -- you can localise the module to your wiki's language. -- -- -- -- To activate a configuration item, you need to uncomment it. This means -- -- that you need to remove the text "-- " at the start of the line. -- -------------------------------------------------------------------------------- local cfg = {} -- Don't edit this line. -------------------------------------------------------------------------------- -- Parameter names -- -- These configuration items specify custom parameter names. Values added -- -- here will work in addition to the default English parameter names. -- -- To add one extra name, you can use this format: -- -- -- -- cfg.foo = 'parameter name' -- -- -- -- To add multiple names, you can use this format: -- -- -- -- cfg.foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'} -- -------------------------------------------------------------------------------- ---- This parameter displays content for the main namespace: -- cfg.main = 'main' ---- This parameter displays in talk namespaces: -- cfg.talk = 'talk' ---- This parameter displays content for "other" namespaces (namespaces for which ---- parameters have not been specified): -- cfg.other = 'other' ---- This parameter makes talk pages behave as though they are the corresponding ---- subject namespace. Note that this parameter is used with [[Module:Yesno]]. ---- Edit that module to change the default values of "yes", "no", etc. -- cfg.subjectns = 'subjectns' ---- This parameter sets a demonstration namespace: -- cfg.demospace = 'demospace' ---- This parameter sets a specific page to compare: cfg.demopage = 'page' -------------------------------------------------------------------------------- -- Table configuration -- -- These configuration items allow customisation of the "table" function, -- -- used to generate a table of possible parameters in the module -- -- documentation. -- -------------------------------------------------------------------------------- ---- The header for the namespace column in the wikitable containing the list of ---- possible subject-space parameters. -- cfg.wikitableNamespaceHeader = 'Namespace' ---- The header for the wikitable containing the list of possible subject-space ---- parameters. -- cfg.wikitableAliasesHeader = 'Aliases' -------------------------------------------------------------------------------- -- End of configuration data -- -------------------------------------------------------------------------------- return cfg -- Don't edit this line. 0e4ff08d13c4b664d66b32c232deb129b77c1a56 Module:Portal 828 64 144 143 2022-09-04T15:24:42Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[==[ This module is a Lua implementation of the old {{Portal}} template. As of February 2019 it is used on nearly 7,900,000 articles. -- Please take care when updating it! It outputs two functions: p.portal, which generates a list of portals, and p.image, which -- produces the image name for an individual portal. -- The portal image data is kept in submodules of [[Module:Portal/images]], listed below: -- [[Module:Portal/images/a]] - for portal names beginning with "A". -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/o]] - for portal names beginning with "O". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/s]] - for portal names beginning with "S". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- [[Module:Portal/images/aliases]] - for adding aliases for existing portal names. Use this page for variations -- in spelling and diacritics, etc., no matter what letter the portal begins with. -- -- The images data pages are separated by the first letter to reduce server load when images are added, changed, or removed. -- Previously all the images were on one data page at [[Module:Portal/images]], but this had the disadvantage that all -- 5,000,000 pages using this module needed to be refreshed every time an image was added or removed. ]==] local p = {} -- determine whether we're being called from a sandbox local isSandbox = mw.getCurrentFrame():getTitle():find('sandbox', 1, true) local sandbox = isSandbox and '/sandbox' or '' local function sandboxVersion(s) return isSandbox and s..'-sand' or s end local templatestyles = 'Module:Portal'..sandbox..'/styles.css' local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') -- List of non-talk namespaces which should not be tracked (Talk pages are never tracked) local badNamespaces = {'user','template','draft','wikipedia'} -- Check whether to do tracking in this namespace -- Returns true unless the page is one of the banned namespaces local function checkTracking(title) local thisPage = title or mw.title.getCurrentTitle() if thisPage.isTalkPage then return false end local ns = thisPage.nsText:lower() for _, v in ipairs(badNamespaces) do if ns == v then return false end end return true end local function matchImagePage(s) -- Finds the appropriate image subpage given a lower-case -- portal name plus the first letter of that portal name. if type(s) ~= 'string' or #s < 1 then return end local firstLetter = mw.ustring.sub(s, 1, 1) local imagePage if mw.ustring.find(firstLetter, '^[a-z]') then imagePage = 'Module:Portal/images/' .. firstLetter .. sandbox else imagePage = 'Module:Portal/images/other' .. sandbox end return mw.loadData(imagePage)[s] end local function getAlias(s) -- Gets an alias from the image alias data page. local aliasData = mw.loadData('Module:Portal/images/aliases'..sandbox) for portal, aliases in pairs(aliasData) do for _, alias in ipairs(aliases) do if alias == s then return portal end end end end local function getImageName(s) -- Gets the image name for a given string. local default = 'Portal-puzzle.svg|link=|alt=' if type(s) ~= 'string' or #s < 1 then return default end s = mw.ustring.lower(s) return matchImagePage(s) or matchImagePage(getAlias(s)) or default end -- Function to check argument portals for errors, generate tracking categories if needed -- Function first checks for too few/many portals provided -- Then checks the portal list to purge any portals that don't exist -- Arguments: -- portals: raw list of portals -- args.tracking: is tracking requested? (will not track on bad titles or namespaces) -- args.redlinks: should redlinks be displayed? -- args.minPortals: minimum number of portal arguments -- args.maxPortals: maximum number of portal arguments -- Returns: -- portals = list of portals, with redlinks purged (if args.redlinks=false) -- trackingCat = possible tracking category -- errorMsg = error message function p._checkPortals(portals, args) local trackingCat = '' local errMsg = nil -- Tracking is on by default. -- It is disabled if any of the following is true -- 1/ the parameter "tracking" is set to 'no, 'n', or 'false' -- 2/ the current page fails the namespace or pagename tests local trackingEnabled = args.tracking and checkTracking() args.minPortals = args.minPortals or 1 args.maxPortals = args.maxPortals or -1 -- check for too few portals if #portals < args.minPortals then errMsg = 'please specify at least '..args.minPortals..' portal'..(args.minPortals > 1 and 's' or '') trackingCat = (trackingEnabled and '[[Category:Portal templates with too few portals]]' or '') return portals, trackingCat, errMsg end -- check for too many portals if args.maxPortals >= 0 and #portals > args.maxPortals then errMsg = 'too many portals (maximum = '..args.maxPortals..')' trackingCat = (trackingEnabled and '[[Category:Portal templates with too many portals]]' or '') return portals, trackingCat, errMsg end if not args.redlinks or trackingEnabled then -- make new list of portals that exist local existingPortals = {} for _, portal in ipairs(portals) do local portalTitle = mw.title.new(portal,"Portal") -- if portal exists, put it into list if portalTitle and portalTitle.exists then table.insert(existingPortals,portal) -- otherwise set tracking cat elseif trackingEnabled then trackingCat = "[[Category:Portal templates with redlinked portals]]" end end -- If redlinks is off, use portal list purged of redlinks portals = args.redlinks and portals or existingPortals -- if nothing left after purge, set tracking cat if #portals == 0 and trackingEnabled then trackingCat = trackingCat.."[[Category:Pages with empty portal template]]" end end return portals, trackingCat, errMsg end function p._portal(portals, args) -- This function builds the portal box used by the {{portal}} template. -- Normalize all arguments if args.redlinks == 'include' then args.redlinks = true end args.addBreak = args['break'] for key, default in pairs({left=false,tracking=true,nominimum=false, redlinks=false,addBreak=false,border=true}) do if args[key] == nil then args[key] = default end args[key] = yesno(args[key], default) end local root = mw.html.create('div') :attr('role', 'navigation') :attr('aria-label', 'Portals') :addClass('noprint plainlist') :addClass(sandboxVersion('portalbox')) :addClass(args.border and sandboxVersion('portalborder') or '') :addClass(args.left and 'tleft' or 'tright') :css('margin', args.margin or nil) :newline() local trackingCat = '' local errMsg = nil args.minPortals = args.nominimum and 0 or 1 args.maxPortals = -1 portals, trackingCat, errMsg = p._checkPortals(portals, args) root:wikitext(trackingCat) -- if error message, put it in the box and return if errMsg then if args.border then -- suppress error message when border=no local errTag = root:tag('strong') errTag:addClass('error') errTag:css('padding','0.2em') errTag:wikitext('Error: '..errMsg) end return tostring(root) end -- if no portals (and no error), just return tracking category if #portals == 0 then return trackingCat end -- Start the list. This corresponds to the start of the wikitext table in the old [[Template:Portal]]. local listroot = root:tag('ul') :css('width', (tonumber(args.boxsize) or 0) > 0 and (args.boxsize .. 'px') or args.boxsize) -- Display the portals specified in the positional arguments. for _, portal in ipairs(portals) do local image = getImageName(portal) -- Generate the html for the image and the portal name. listroot :newline() :tag('li') :tag('span') :wikitext(string.format('[[File:%s|32x28px|class=noviewer]]', image)) :done() :tag('span') :wikitext(string.format('[[Portal:%s|%s%sportal]]', portal, portal, args.addBreak and '<br />' or ' ')) end return tostring(root) end function p._image(portal,nostrip) -- Wrapper function to allow getImageName() to be accessed through #invoke. -- backward compatibility: if table passed, take first element if type(portal) == 'table' then portal = portal[1] end local name = getImageName(portal) -- If nostrip is yes (or equivalent), then allow all metadata (like image borders) to be returned local strip = not yesno(nostrip) return strip and name:match('^(.-)|') or name -- FIXME: use a more elegant way to separate borders etc. from the image name end local function getAllImageTables() -- Returns an array containing all image subpages (minus aliases) as loaded by mw.loadData. local images = {} for i, subpage in ipairs{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'other'} do images[i] = mw.loadData('Module:Portal/images/' .. subpage .. sandbox) end return images end function p._displayAll(portals, args) -- This function displays all portals that have portal images. This function is for maintenance purposes and should not be used in -- articles, for two reasons: 1) there are over 1500 portals with portal images, and 2) the module doesn't record how the portal -- names are capitalized, so the portal links may be broken. local lang = mw.language.getContentLanguage() local count = 1 for _, imageTable in ipairs(getAllImageTables()) do for portal in pairs(imageTable) do portals[count] = lang:ucfirst(portal) count = count + 1 end end return p._portal(portals, args) end function p._imageDupes() -- This function searches the image subpages to find duplicate images. If duplicate images exist, it is not necessarily a bad thing, -- as different portals might just happen to choose the same image. However, this function is helpful in identifying images that -- should be moved to a portal alias for ease of maintenance. local exists, dupes = {}, {} for _, imageTable in ipairs(getAllImageTables()) do for portal, image in pairs(imageTable) do if not exists[image] then exists[image] = portal else table.insert(dupes, string.format('The image "[[:File:%s|%s]]" is used for both portals "%s" and "%s".', image, image, exists[image], portal)) end end end if #dupes < 1 then return 'No duplicate images found.' else return 'The following duplicate images were found:\n* ' .. table.concat(dupes, '\n* ') end end local function processPortalArgs(args) -- This function processes a table of arguments and returns two tables: an array of portal names for processing by ipairs, and a table of -- the named arguments that specify style options, etc. We need to use ipairs because we want to list all the portals in the order -- they were passed to the template, but we also want to be able to deal with positional arguments passed explicitly, for example -- {{portal|2=Politics}}. The behaviour of ipairs is undefined if nil values are present, so we need to make sure they are all removed. args = type(args) == 'table' and args or {} local portals = {} local namedArgs = {} for k, v in pairs(args) do if type(k) == 'number' and type(v) == 'string' then -- Make sure we have no non-string portal names. table.insert(portals, k) elseif type(k) ~= 'number' then namedArgs[k] = v end end table.sort(portals) for i, v in ipairs(portals) do portals[i] = args[v] end return portals, namedArgs end -- Entry point for sorting portals from other named arguments function p._processPortalArgs(args) return processPortalArgs(args) end function p.image(frame) local origArgs = getArgs(frame) local portals, args = processPortalArgs(origArgs) return p._image(portals[1],args.border) end local function makeWrapper(funcName) -- Processes external arguments and sends them to the other functions. return function (frame) -- If called via #invoke, use the args passed into the invoking -- template, or the args passed to #invoke if any exist. Otherwise -- assume args are being passed directly in from the debug console -- or from another Lua module. -- Also: trim whitespace and remove blank arguments local origArgs = getArgs(frame) -- create two tables to pass to func: an array of portal names, and a table of named arguments. local portals, args = processPortalArgs(origArgs) local results = '' if funcName == '_portal' or funcName == '_displayAll' then results = frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles} } end return results .. p[funcName](portals, args) end end for _, funcName in ipairs{'portal', 'imageDupes', 'displayAll'} do p[funcName] = makeWrapper('_' .. funcName) end return p 078bc1925b1a76f62f668379257fd789d6d85d4b Template:Short description 10 65 146 145 2022-09-04T15:24:43Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#ifeq:{{lc:{{{1|}}}}}|none|<nowiki /><!--Prevents whitespace issues when used with adjacent newlines-->|<div class="shortdescription nomobile noexcerpt noprint searchaux" style="display:none">{{{1|}}}{{SHORTDESC:{{{1|}}}|{{{2|}}}}}</div>}}<includeonly>{{#ifeq:{{pagetype |defaultns = all |user=exclude}}|exclude||[[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with short description{{#ifeq:{{{pagetype}}}|Disambiguation pages|s}}]]}}</includeonly><!-- Start tracking -->{{#invoke:Check for unknown parameters|check|unknown={{Main other|[[Category:Pages using short description with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Short description]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | 2 | pagetype | bot |plural }}<!-- -->{{#ifexpr: {{#invoke:String|len|{{{1|}}}}}>100 | [[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with long short description]]}}<!-- -->{{Short description/lowercasecheck|{{{1|}}}}}<!-- -->{{Main other |{{SDcat |sd={{{1|}}} }} }}<noinclude> {{Documentation}} </noinclude> a9562f8e6077b84b83132612ac9a5b37c58485b3 Template:Main other 10 66 148 147 2022-09-04T15:24:43Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#switch: <!--If no or empty "demospace" parameter then detect namespace--> {{#if:{{{demospace|}}} | {{lc: {{{demospace}}} }} <!--Use lower case "demospace"--> | {{#ifeq:{{NAMESPACE}}|{{ns:0}} | main | other }} }} | main = {{{1|}}} | other | #default = {{{2|}}} }}<noinclude> {{documentation}} <!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! --> </noinclude> 86ad907ffeea3cc545159e00cd1f2d6433946450 Template:Short description/lowercasecheck 10 67 150 149 2022-09-04T15:24:43Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#ifeq:<!--test first character for lower-case letter-->{{#invoke:string|find|1={{{1|}}}|2=^%l|plain=false}}|1 |<!-- first character is a lower case letter; test against whitelist -->{{#switch: {{First word|{{{1|}}}}}<!--begin whitelist--> |c. <!--for circa--> |gTLD |iMac |iOS |iOS, |iPad |iPhone |iTunes |macOS |none |pH |pH-dependent=<!-- end whitelist; short description starts with an allowed lower-case string; whitelist matched; do nothing --> |#default=<!-- apply category to track lower-case short descriptions -->{{main other|[[Category:Pages with lower-case short description|{{trim|{{{1|}}}}}]]}}{{Testcases other|{{red|CATEGORY APPLIED}}}}<!-- end whitelist test -->}} |<!-- short description does not start with lower-case letter; do nothing; end lower-case test --> }}<noinclude> {{documentation}} </noinclude> 9a6d4db14b74614625fd234b4f8ee3c8e1a235c0 Template:SDcat 10 68 152 151 2022-09-04T15:24:44Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:SDcat |setCat}}</includeonly><noinclude> {{documentation}} </noinclude> 8c6e8783ddb0dc699d6fb60370db97b73725b9a6 Template:Str rep 10 69 154 153 2022-09-04T15:24:44Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#invoke:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|1}}<noinclude> {{Documentation}}</noinclude> 4706daa3137857f2792cc7109ca24b6d58c78dee Module:Check for unknown parameters 828 70 156 155 2022-09-04T15:24:44Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module may be used to compare the arguments passed to the parent -- with a list of arguments, returning a specified result if an argument is -- not on the list local p = {} local function trim(s) return s:match('^%s*(.-)%s*$') end local function isnotempty(s) return s and s:match('%S') end local function clean(text) -- Return text cleaned for display and truncated if too long. -- Strip markers are replaced with dummy text representing the original wikitext. local pos, truncated local function truncate(text) if truncated then return '' end if mw.ustring.len(text) > 25 then truncated = true text = mw.ustring.sub(text, 1, 25) .. '...' end return mw.text.nowiki(text) end local parts = {} for before, tag, remainder in text:gmatch('([^\127]*)\127[^\127]*%-(%l+)%-[^\127]*\127()') do pos = remainder table.insert(parts, truncate(before) .. '&lt;' .. tag .. '&gt;...&lt;/' .. tag .. '&gt;') end table.insert(parts, truncate(text:sub(pos or 1))) return table.concat(parts) end function p._check(args, pargs) if type(args) ~= "table" or type(pargs) ~= "table" then -- TODO: error handling return end -- create the list of known args, regular expressions, and the return string local knownargs = {} local regexps = {} for k, v in pairs(args) do if type(k) == 'number' then v = trim(v) knownargs[v] = 1 elseif k:find('^regexp[1-9][0-9]*$') then table.insert(regexps, '^' .. v .. '$') end end -- loop over the parent args, and make sure they are on the list local ignoreblank = isnotempty(args['ignoreblank']) local showblankpos = isnotempty(args['showblankpositional']) local values = {} for k, v in pairs(pargs) do if type(k) == 'string' and knownargs[k] == nil then local knownflag = false for _, regexp in ipairs(regexps) do if mw.ustring.match(k, regexp) then knownflag = true break end end if not knownflag and ( not ignoreblank or isnotempty(v) ) then table.insert(values, clean(k)) end elseif type(k) == 'number' and knownargs[tostring(k)] == nil then local knownflag = false for _, regexp in ipairs(regexps) do if mw.ustring.match(tostring(k), regexp) then knownflag = true break end end if not knownflag and ( showblankpos or isnotempty(v) ) then table.insert(values, k .. ' = ' .. clean(v)) end end end -- add results to the output tables local res = {} if #values > 0 then local unknown_text = args['unknown'] or 'Found _VALUE_, ' if mw.getCurrentFrame():preprocess( "{{REVISIONID}}" ) == "" then local preview_text = args['preview'] if isnotempty(preview_text) then preview_text = require('Module:If preview')._warning({preview_text}) elseif preview == nil then preview_text = unknown_text end unknown_text = preview_text end for _, v in pairs(values) do -- Fix odd bug for | = which gets stripped to the empty string and -- breaks category links if v == '' then v = ' ' end -- avoid error with v = 'example%2' ("invalid capture index") local r = unknown_text:gsub('_VALUE_', {_VALUE_ = v}) table.insert(res, r) end end return table.concat(res) end function p.check(frame) local args = frame.args local pargs = frame:getParent().args return p._check(args, pargs) end return p 93db6d115d4328d2a5148bb42959105e367b663e Module:String 828 71 158 157 2022-09-04T15:24:45Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[ This module is intended to provide access to basic string functions. Most of the functions provided here can be invoked with named parameters, unnamed parameters, or a mixture. If named parameters are used, Mediawiki will automatically remove any leading or trailing whitespace from the parameter. Depending on the intended use, it may be advantageous to either preserve or remove such whitespace. Global options ignore_errors: If set to 'true' or 1, any error condition will result in an empty string being returned rather than an error message. error_category: If an error occurs, specifies the name of a category to include with the error message. The default category is [Category:Errors reported by Module String]. no_category: If set to 'true' or 1, no category will be added if an error is generated. Unit tests for this module are available at Module:String/tests. ]] local str = {} --[[ len This function returns the length of the target string. Usage: {{#invoke:String|len|target_string|}} OR {{#invoke:String|len|s=target_string}} Parameters s: The string whose length to report If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from the target string. ]] function str.len( frame ) local new_args = str._getParameters( frame.args, {'s'} ) local s = new_args['s'] or '' return mw.ustring.len( s ) end --[[ sub This function returns a substring of the target string at specified indices. Usage: {{#invoke:String|sub|target_string|start_index|end_index}} OR {{#invoke:String|sub|s=target_string|i=start_index|j=end_index}} Parameters s: The string to return a subset of i: The fist index of the substring to return, defaults to 1. j: The last index of the string to return, defaults to the last character. The first character of the string is assigned an index of 1. If either i or j is a negative value, it is interpreted the same as selecting a character by counting from the end of the string. Hence, a value of -1 is the same as selecting the last character of the string. If the requested indices are out of range for the given string, an error is reported. ]] function str.sub( frame ) local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } ) local s = new_args['s'] or '' local i = tonumber( new_args['i'] ) or 1 local j = tonumber( new_args['j'] ) or -1 local len = mw.ustring.len( s ) -- Convert negatives for range checking if i < 0 then i = len + i + 1 end if j < 0 then j = len + j + 1 end if i > len or j > len or i < 1 or j < 1 then return str._error( 'String subset index out of range' ) end if j < i then return str._error( 'String subset indices out of order' ) end return mw.ustring.sub( s, i, j ) end --[[ This function implements that features of {{str sub old}} and is kept in order to maintain these older templates. ]] function str.sublength( frame ) local i = tonumber( frame.args.i ) or 0 local len = tonumber( frame.args.len ) return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) ) end --[[ _match This function returns a substring from the source string that matches a specified pattern. It is exported for use in other modules Usage: strmatch = require("Module:String")._match sresult = strmatch( s, pattern, start, match, plain, nomatch ) Parameters s: The string to search pattern: The pattern or string to find within the string start: The index within the source string to start the search. The first character of the string has index 1. Defaults to 1. match: In some cases it may be possible to make multiple matches on a single string. This specifies which match to return, where the first match is match= 1. If a negative number is specified then a match is returned counting from the last match. Hence match = -1 is the same as requesting the last match. Defaults to 1. plain: A flag indicating that the pattern should be understood as plain text. Defaults to false. nomatch: If no match is found, output the "nomatch" value rather than an error. For information on constructing Lua patterns, a form of [regular expression], see: * http://www.lua.org/manual/5.1/manual.html#5.4.1 * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns ]] -- This sub-routine is exported for use in other modules function str._match( s, pattern, start, match_index, plain_flag, nomatch ) if s == '' then return str._error( 'Target string is empty' ) end if pattern == '' then return str._error( 'Pattern string is empty' ) end start = tonumber(start) or 1 if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then return str._error( 'Requested start is out of range' ) end if match_index == 0 then return str._error( 'Match index is out of range' ) end if plain_flag then pattern = str._escapePattern( pattern ) end local result if match_index == 1 then -- Find first match is simple case result = mw.ustring.match( s, pattern, start ) else if start > 1 then s = mw.ustring.sub( s, start ) end local iterator = mw.ustring.gmatch(s, pattern) if match_index > 0 then -- Forward search for w in iterator do match_index = match_index - 1 if match_index == 0 then result = w break end end else -- Reverse search local result_table = {} local count = 1 for w in iterator do result_table[count] = w count = count + 1 end result = result_table[ count + match_index ] end end if result == nil then if nomatch == nil then return str._error( 'Match not found' ) else return nomatch end else return result end end --[[ match This function returns a substring from the source string that matches a specified pattern. Usage: {{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}} OR {{#invoke:String|match|s=source_string|pattern=pattern_string|start=start_index |match=match_number|plain=plain_flag|nomatch=nomatch_output}} Parameters s: The string to search pattern: The pattern or string to find within the string start: The index within the source string to start the search. The first character of the string has index 1. Defaults to 1. match: In some cases it may be possible to make multiple matches on a single string. This specifies which match to return, where the first match is match= 1. If a negative number is specified then a match is returned counting from the last match. Hence match = -1 is the same as requesting the last match. Defaults to 1. plain: A flag indicating that the pattern should be understood as plain text. Defaults to false. nomatch: If no match is found, output the "nomatch" value rather than an error. If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from each string. In some circumstances this is desirable, in other cases one may want to preserve the whitespace. If the match_number or start_index are out of range for the string being queried, then this function generates an error. An error is also generated if no match is found. If one adds the parameter ignore_errors=true, then the error will be suppressed and an empty string will be returned on any failure. For information on constructing Lua patterns, a form of [regular expression], see: * http://www.lua.org/manual/5.1/manual.html#5.4.1 * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns ]] -- This is the entry point for #invoke:String|match function str.match( frame ) local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} ) local s = new_args['s'] or '' local start = tonumber( new_args['start'] ) or 1 local plain_flag = str._getBoolean( new_args['plain'] or false ) local pattern = new_args['pattern'] or '' local match_index = math.floor( tonumber(new_args['match']) or 1 ) local nomatch = new_args['nomatch'] return str._match( s, pattern, start, match_index, plain_flag, nomatch ) end --[[ pos This function returns a single character from the target string at position pos. Usage: {{#invoke:String|pos|target_string|index_value}} OR {{#invoke:String|pos|target=target_string|pos=index_value}} Parameters target: The string to search pos: The index for the character to return If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from the target string. In some circumstances this is desirable, in other cases one may want to preserve the whitespace. The first character has an index value of 1. If one requests a negative value, this function will select a character by counting backwards from the end of the string. In other words pos = -1 is the same as asking for the last character. A requested value of zero, or a value greater than the length of the string returns an error. ]] function str.pos( frame ) local new_args = str._getParameters( frame.args, {'target', 'pos'} ) local target_str = new_args['target'] or '' local pos = tonumber( new_args['pos'] ) or 0 if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then return str._error( 'String index out of range' ) end return mw.ustring.sub( target_str, pos, pos ) end --[[ str_find This function duplicates the behavior of {{str_find}}, including all of its quirks. This is provided in order to support existing templates, but is NOT RECOMMENDED for new code and templates. New code is recommended to use the "find" function instead. Returns the first index in "source" that is a match to "target". Indexing is 1-based, and the function returns -1 if the "target" string is not present in "source". Important Note: If the "target" string is empty / missing, this function returns a value of "1", which is generally unexpected behavior, and must be accounted for separatetly. ]] function str.str_find( frame ) local new_args = str._getParameters( frame.args, {'source', 'target'} ) local source_str = new_args['source'] or '' local target_str = new_args['target'] or '' if target_str == '' then return 1 end local start = mw.ustring.find( source_str, target_str, 1, true ) if start == nil then start = -1 end return start end --[[ find This function allows one to search for a target string or pattern within another string. Usage: {{#invoke:String|find|source_str|target_string|start_index|plain_flag}} OR {{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}} Parameters source: The string to search target: The string or pattern to find within source start: The index within the source string to start the search, defaults to 1 plain: Boolean flag indicating that target should be understood as plain text and not as a Lua style regular expression, defaults to true If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from the parameter. In some circumstances this is desirable, in other cases one may want to preserve the whitespace. This function returns the first index >= "start" where "target" can be found within "source". Indices are 1-based. If "target" is not found, then this function returns 0. If either "source" or "target" are missing / empty, this function also returns 0. This function should be safe for UTF-8 strings. ]] function str.find( frame ) local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } ) local source_str = new_args['source'] or '' local pattern = new_args['target'] or '' local start_pos = tonumber(new_args['start']) or 1 local plain = new_args['plain'] or true if source_str == '' or pattern == '' then return 0 end plain = str._getBoolean( plain ) local start = mw.ustring.find( source_str, pattern, start_pos, plain ) if start == nil then start = 0 end return start end --[[ replace This function allows one to replace a target string or pattern within another string. Usage: {{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}} OR {{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string| count=replacement_count|plain=plain_flag}} Parameters source: The string to search pattern: The string or pattern to find within source replace: The replacement text count: The number of occurences to replace, defaults to all. plain: Boolean flag indicating that pattern should be understood as plain text and not as a Lua style regular expression, defaults to true ]] function str.replace( frame ) local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } ) local source_str = new_args['source'] or '' local pattern = new_args['pattern'] or '' local replace = new_args['replace'] or '' local count = tonumber( new_args['count'] ) local plain = new_args['plain'] or true if source_str == '' or pattern == '' then return source_str end plain = str._getBoolean( plain ) if plain then pattern = str._escapePattern( pattern ) replace = mw.ustring.gsub( replace, "%%", "%%%%" ) --Only need to escape replacement sequences. end local result if count ~= nil then result = mw.ustring.gsub( source_str, pattern, replace, count ) else result = mw.ustring.gsub( source_str, pattern, replace ) end return result end --[[ simple function to pipe string.rep to templates. ]] function str.rep( frame ) local repetitions = tonumber( frame.args[2] ) if not repetitions then return str._error( 'function rep expects a number as second parameter, received "' .. ( frame.args[2] or '' ) .. '"' ) end return string.rep( frame.args[1] or '', repetitions ) end --[[ escapePattern This function escapes special characters from a Lua string pattern. See [1] for details on how patterns work. [1] https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns Usage: {{#invoke:String|escapePattern|pattern_string}} Parameters pattern_string: The pattern string to escape. ]] function str.escapePattern( frame ) local pattern_str = frame.args[1] if not pattern_str then return str._error( 'No pattern string specified' ) end local result = str._escapePattern( pattern_str ) return result end --[[ count This function counts the number of occurrences of one string in another. ]] function str.count(frame) local args = str._getParameters(frame.args, {'source', 'pattern', 'plain'}) local source = args.source or '' local pattern = args.pattern or '' local plain = str._getBoolean(args.plain or true) if plain then pattern = str._escapePattern(pattern) end local _, count = mw.ustring.gsub(source, pattern, '') return count end --[[ endswith This function determines whether a string ends with another string. ]] function str.endswith(frame) local args = str._getParameters(frame.args, {'source', 'pattern'}) local source = args.source or '' local pattern = args.pattern or '' if pattern == '' then -- All strings end with the empty string. return "yes" end if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then return "yes" else return "" end end --[[ join Join all non empty arguments together; the first argument is the separator. Usage: {{#invoke:String|join|sep|one|two|three}} ]] function str.join(frame) local args = {} local sep for _, v in ipairs( frame.args ) do if sep then if v ~= '' then table.insert(args, v) end else sep = v end end return table.concat( args, sep or '' ) end --[[ Helper function that populates the argument list given that user may need to use a mix of named and unnamed parameters. This is relevant because named parameters are not identical to unnamed parameters due to string trimming, and when dealing with strings we sometimes want to either preserve or remove that whitespace depending on the application. ]] function str._getParameters( frame_args, arg_list ) local new_args = {} local index = 1 local value for _, arg in ipairs( arg_list ) do value = frame_args[arg] if value == nil then value = frame_args[index] index = index + 1 end new_args[arg] = value end return new_args end --[[ Helper function to handle error messages. ]] function str._error( error_str ) local frame = mw.getCurrentFrame() local error_category = frame.args.error_category or 'Errors reported by Module String' local ignore_errors = frame.args.ignore_errors or false local no_category = frame.args.no_category or false if str._getBoolean(ignore_errors) then return '' end local error_str = '<strong class="error">String Module Error: ' .. error_str .. '</strong>' if error_category ~= '' and not str._getBoolean( no_category ) then error_str = '[[Category:' .. error_category .. ']]' .. error_str end return error_str end --[[ Helper Function to interpret boolean strings ]] function str._getBoolean( boolean_str ) local boolean_value if type( boolean_str ) == 'string' then boolean_str = boolean_str:lower() if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0' or boolean_str == '' then boolean_value = false else boolean_value = true end elseif type( boolean_str ) == 'boolean' then boolean_value = boolean_str else error( 'No boolean value found' ) end return boolean_value end --[[ Helper function that escapes all pattern characters so that they will be treated as plain text. ]] function str._escapePattern( pattern_str ) return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ) end return str 6df794dd52434e0f6a372c9918f5a9dedd15f579 Module:SDcat 828 72 160 159 2022-09-04T15:24:45Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[ SDcat Module to check whether local short description matches that on Wikidata --]] local p = {} ------------------------------------------------------------------------------- --[[ setCat has the qid of a Wikidata entity passed as |qid= (it defaults to the associated qid of the current article if omitted) and the local short description passed as |sd= It returns a category if there is an associated Wikidata entity. It returns one of the following tracking categories, as appropriate: * Category:Short description matches Wikidata (case-insensitive) * Category:Short description is different from Wikidata * Category:Short description with empty Wikidata description For testing purposes, a link prefix |lp= may be set to ":" to make the categories visible. --]] -- function exported for use in other modules -- (local short description, Wikidata entity-ID, link prefix) p._setCat = function(sdesc, itemID, lp) if not mw.wikibase then return nil end if itemID == "" then itemID = nil end -- Wikidata description field local wdesc = (mw.wikibase.getDescription(itemID) or ""):lower() if wdesc == "" then return "[[" .. lp .. "Category:Short description with empty Wikidata description]]" elseif wdesc == sdesc then return "[[" .. lp .. "Category:Short description matches Wikidata]]" else return "[[" .. lp .. "Category:Short description is different from Wikidata]]" end end -- function exported for call from #invoke p.setCat = function(frame) local args if frame.args.sd then args = frame.args else args = frame:getParent().args end -- local short description local sdesc = mw.text.trim(args.sd or ""):lower() -- Wikidata entity-ID local itemID = mw.text.trim(args.qid or "") -- link prefix, strip quotes local lp = mw.text.trim(args.lp or ""):gsub('"', '') return p._setCat(sdesc, itemID, lp) end return p 6c19ac0f72c79a618eb105808f74701376bb2b38 Module:TableTools 828 73 162 161 2022-09-04T15:24:46Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain ------------------------------------------------------------------------------------ -- TableTools -- -- -- -- This module includes a number of functions for dealing with Lua tables. -- -- It is a meta-module, meant to be called from other Lua modules, and should not -- -- be called directly from #invoke. -- ------------------------------------------------------------------------------------ local libraryUtil = require('libraryUtil') local p = {} -- Define often-used variables and functions. local floor = math.floor local infinity = math.huge local checkType = libraryUtil.checkType local checkTypeMulti = libraryUtil.checkTypeMulti ------------------------------------------------------------------------------------ -- isPositiveInteger -- -- This function returns true if the given value is a positive integer, and false -- if not. Although it doesn't operate on tables, it is included here as it is -- useful for determining whether a given table key is in the array part or the -- hash part of a table. ------------------------------------------------------------------------------------ function p.isPositiveInteger(v) return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity end ------------------------------------------------------------------------------------ -- isNan -- -- This function returns true if the given number is a NaN value, and false if -- not. Although it doesn't operate on tables, it is included here as it is useful -- for determining whether a value can be a valid table key. Lua will generate an -- error if a NaN is used as a table key. ------------------------------------------------------------------------------------ function p.isNan(v) return type(v) == 'number' and v ~= v end ------------------------------------------------------------------------------------ -- shallowClone -- -- This returns a clone of a table. The value returned is a new table, but all -- subtables and functions are shared. Metamethods are respected, but the returned -- table will have no metatable of its own. ------------------------------------------------------------------------------------ function p.shallowClone(t) checkType('shallowClone', 1, t, 'table') local ret = {} for k, v in pairs(t) do ret[k] = v end return ret end ------------------------------------------------------------------------------------ -- removeDuplicates -- -- This removes duplicate values from an array. Non-positive-integer keys are -- ignored. The earliest value is kept, and all subsequent duplicate values are -- removed, but otherwise the array order is unchanged. ------------------------------------------------------------------------------------ function p.removeDuplicates(arr) checkType('removeDuplicates', 1, arr, 'table') local isNan = p.isNan local ret, exists = {}, {} for _, v in ipairs(arr) do if isNan(v) then -- NaNs can't be table keys, and they are also unique, so we don't need to check existence. ret[#ret + 1] = v else if not exists[v] then ret[#ret + 1] = v exists[v] = true end end end return ret end ------------------------------------------------------------------------------------ -- numKeys -- -- This takes a table and returns an array containing the numbers of any numerical -- keys that have non-nil values, sorted in numerical order. ------------------------------------------------------------------------------------ function p.numKeys(t) checkType('numKeys', 1, t, 'table') local isPositiveInteger = p.isPositiveInteger local nums = {} for k in pairs(t) do if isPositiveInteger(k) then nums[#nums + 1] = k end end table.sort(nums) return nums end ------------------------------------------------------------------------------------ -- affixNums -- -- This takes a table and returns an array containing the numbers of keys with the -- specified prefix and suffix. For example, for the table -- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will return -- {1, 3, 6}. ------------------------------------------------------------------------------------ function p.affixNums(t, prefix, suffix) checkType('affixNums', 1, t, 'table') checkType('affixNums', 2, prefix, 'string', true) checkType('affixNums', 3, suffix, 'string', true) local function cleanPattern(s) -- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally. return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1') end prefix = prefix or '' suffix = suffix or '' prefix = cleanPattern(prefix) suffix = cleanPattern(suffix) local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$' local nums = {} for k in pairs(t) do if type(k) == 'string' then local num = mw.ustring.match(k, pattern) if num then nums[#nums + 1] = tonumber(num) end end end table.sort(nums) return nums end ------------------------------------------------------------------------------------ -- numData -- -- Given a table with keys like {"foo1", "bar1", "foo2", "baz2"}, returns a table -- of subtables in the format -- {[1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'}}. -- Keys that don't end with an integer are stored in a subtable named "other". The -- compress option compresses the table so that it can be iterated over with -- ipairs. ------------------------------------------------------------------------------------ function p.numData(t, compress) checkType('numData', 1, t, 'table') checkType('numData', 2, compress, 'boolean', true) local ret = {} for k, v in pairs(t) do local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$') if num then num = tonumber(num) local subtable = ret[num] or {} if prefix == '' then -- Positional parameters match the blank string; put them at the start of the subtable instead. prefix = 1 end subtable[prefix] = v ret[num] = subtable else local subtable = ret.other or {} subtable[k] = v ret.other = subtable end end if compress then local other = ret.other ret = p.compressSparseArray(ret) ret.other = other end return ret end ------------------------------------------------------------------------------------ -- compressSparseArray -- -- This takes an array with one or more nil values, and removes the nil values -- while preserving the order, so that the array can be safely traversed with -- ipairs. ------------------------------------------------------------------------------------ function p.compressSparseArray(t) checkType('compressSparseArray', 1, t, 'table') local ret = {} local nums = p.numKeys(t) for _, num in ipairs(nums) do ret[#ret + 1] = t[num] end return ret end ------------------------------------------------------------------------------------ -- sparseIpairs -- -- This is an iterator for sparse arrays. It can be used like ipairs, but can -- handle nil values. ------------------------------------------------------------------------------------ function p.sparseIpairs(t) checkType('sparseIpairs', 1, t, 'table') local nums = p.numKeys(t) local i = 0 local lim = #nums return function () i = i + 1 if i <= lim then local key = nums[i] return key, t[key] else return nil, nil end end end ------------------------------------------------------------------------------------ -- size -- -- This returns the size of a key/value pair table. It will also work on arrays, -- but for arrays it is more efficient to use the # operator. ------------------------------------------------------------------------------------ function p.size(t) checkType('size', 1, t, 'table') local i = 0 for _ in pairs(t) do i = i + 1 end return i end local function defaultKeySort(item1, item2) -- "number" < "string", so numbers will be sorted before strings. local type1, type2 = type(item1), type(item2) if type1 ~= type2 then return type1 < type2 elseif type1 == 'table' or type1 == 'boolean' or type1 == 'function' then return tostring(item1) < tostring(item2) else return item1 < item2 end end ------------------------------------------------------------------------------------ -- keysToList -- -- Returns an array of the keys in a table, sorted using either a default -- comparison function or a custom keySort function. ------------------------------------------------------------------------------------ function p.keysToList(t, keySort, checked) if not checked then checkType('keysToList', 1, t, 'table') checkTypeMulti('keysToList', 2, keySort, {'function', 'boolean', 'nil'}) end local arr = {} local index = 1 for k in pairs(t) do arr[index] = k index = index + 1 end if keySort ~= false then keySort = type(keySort) == 'function' and keySort or defaultKeySort table.sort(arr, keySort) end return arr end ------------------------------------------------------------------------------------ -- sortedPairs -- -- Iterates through a table, with the keys sorted using the keysToList function. -- If there are only numerical keys, sparseIpairs is probably more efficient. ------------------------------------------------------------------------------------ function p.sortedPairs(t, keySort) checkType('sortedPairs', 1, t, 'table') checkType('sortedPairs', 2, keySort, 'function', true) local arr = p.keysToList(t, keySort, true) local i = 0 return function () i = i + 1 local key = arr[i] if key ~= nil then return key, t[key] else return nil, nil end end end ------------------------------------------------------------------------------------ -- isArray -- -- Returns true if the given value is a table and all keys are consecutive -- integers starting at 1. ------------------------------------------------------------------------------------ function p.isArray(v) if type(v) ~= 'table' then return false end local i = 0 for _ in pairs(v) do i = i + 1 if v[i] == nil then return false end end return true end ------------------------------------------------------------------------------------ -- isArrayLike -- -- Returns true if the given value is iterable and all keys are consecutive -- integers starting at 1. ------------------------------------------------------------------------------------ function p.isArrayLike(v) if not pcall(pairs, v) then return false end local i = 0 for _ in pairs(v) do i = i + 1 if v[i] == nil then return false end end return true end ------------------------------------------------------------------------------------ -- invert -- -- Transposes the keys and values in an array. For example, {"a", "b", "c"} -> -- {a = 1, b = 2, c = 3}. Duplicates are not supported (result values refer to -- the index of the last duplicate) and NaN values are ignored. ------------------------------------------------------------------------------------ function p.invert(arr) checkType("invert", 1, arr, "table") local isNan = p.isNan local map = {} for i, v in ipairs(arr) do if not isNan(v) then map[v] = i end end return map end ------------------------------------------------------------------------------------ -- listToSet -- -- Creates a set from the array part of the table. Indexing the set by any of the -- values of the array returns true. For example, {"a", "b", "c"} -> -- {a = true, b = true, c = true}. NaN values are ignored as Lua considers them -- never equal to any value (including other NaNs or even themselves). ------------------------------------------------------------------------------------ function p.listToSet(arr) checkType("listToSet", 1, arr, "table") local isNan = p.isNan local set = {} for _, v in ipairs(arr) do if not isNan(v) then set[v] = true end end return set end ------------------------------------------------------------------------------------ -- deepCopy -- -- Recursive deep copy function. Preserves identities of subtables. ------------------------------------------------------------------------------------ local function _deepCopy(orig, includeMetatable, already_seen) -- Stores copies of tables indexed by the original table. already_seen = already_seen or {} local copy = already_seen[orig] if copy ~= nil then return copy end if type(orig) == 'table' then copy = {} for orig_key, orig_value in pairs(orig) do copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen) end already_seen[orig] = copy if includeMetatable then local mt = getmetatable(orig) if mt ~= nil then local mt_copy = _deepCopy(mt, includeMetatable, already_seen) setmetatable(copy, mt_copy) already_seen[mt] = mt_copy end end else -- number, string, boolean, etc copy = orig end return copy end function p.deepCopy(orig, noMetatable, already_seen) checkType("deepCopy", 3, already_seen, "table", true) return _deepCopy(orig, not noMetatable, already_seen) end ------------------------------------------------------------------------------------ -- sparseConcat -- -- Concatenates all values in the table that are indexed by a number, in order. -- sparseConcat{a, nil, c, d} => "acd" -- sparseConcat{nil, b, c, d} => "bcd" ------------------------------------------------------------------------------------ function p.sparseConcat(t, sep, i, j) local arr = {} local arr_i = 0 for _, v in p.sparseIpairs(t) do arr_i = arr_i + 1 arr[arr_i] = v end return table.concat(arr, sep, i, j) end ------------------------------------------------------------------------------------ -- length -- -- Finds the length of an array, or of a quasi-array with keys such as "data1", -- "data2", etc., using an exponential search algorithm. It is similar to the -- operator #, but may return a different value when there are gaps in the array -- portion of the table. Intended to be used on data loaded with mw.loadData. For -- other tables, use #. -- Note: #frame.args in frame object always be set to 0, regardless of the number -- of unnamed template parameters, so use this function for frame.args. ------------------------------------------------------------------------------------ function p.length(t, prefix) -- requiring module inline so that [[Module:Exponential search]] which is -- only needed by this one function doesn't get millions of transclusions local expSearch = require("Module:Exponential search") checkType('length', 1, t, 'table') checkType('length', 2, prefix, 'string', true) return expSearch(function (i) local key if prefix then key = prefix .. tostring(i) else key = i end return t[key] ~= nil end) or 0 end ------------------------------------------------------------------------------------ -- inArray -- -- Returns true if valueToFind is a member of the array, and false otherwise. ------------------------------------------------------------------------------------ function p.inArray(arr, valueToFind) checkType("inArray", 1, arr, "table") -- if valueToFind is nil, error? for _, v in ipairs(arr) do if v == valueToFind then return true end end return false end return p 085e7094ac84eb0132ee65822cf3f69cd8ba3d81 Module:Separated entries 828 74 164 163 2022-09-04T15:24:46Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module takes positional parameters as input and concatenates them with -- an optional separator. The final separator (the "conjunction") can be -- specified independently, enabling natural-language lists like -- "foo, bar, baz and qux". The starting parameter can also be specified. local compressSparseArray = require('Module:TableTools').compressSparseArray local p = {} function p._main(args) local separator = args.separator -- Decode (convert to Unicode) HTML escape sequences, such as "&#32;" for space. and mw.text.decode(args.separator) or '' local conjunction = args.conjunction and mw.text.decode(args.conjunction) or separator -- Discard values before the starting parameter. local start = tonumber(args.start) if start then for i = 1, start - 1 do args[i] = nil end end -- Discard named parameters. local values = compressSparseArray(args) return mw.text.listToText(values, separator, conjunction) end local function makeInvokeFunction(separator, conjunction, first) return function (frame) local args = require('Module:Arguments').getArgs(frame) args.separator = separator or args.separator args.conjunction = conjunction or args.conjunction args.first = first or args.first return p._main(args) end end p.main = makeInvokeFunction() p.br = makeInvokeFunction('<br />') p.comma = makeInvokeFunction(mw.message.new('comma-separator'):plain()) return p e80231ff3de01afd7f62a94e0a34dc1e67504085 Module:Category handler 828 75 166 165 2022-09-04T15:24:46Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- -- -- CATEGORY HANDLER -- -- -- -- This module implements the {{category handler}} template in Lua, -- -- with a few improvements: all namespaces and all namespace aliases -- -- are supported, and namespace names are detected automatically for -- -- the local wiki. This module requires [[Module:Namespace detect]] -- -- and [[Module:Yesno]] to be available on the local wiki. It can be -- -- configured for different wikis by altering the values in -- -- [[Module:Category handler/config]], and pages can be blacklisted -- -- from categorisation by using [[Module:Category handler/blacklist]]. -- -- -- -------------------------------------------------------------------------------- -- Load required modules local yesno = require('Module:Yesno') -- Lazily load things we don't always need local mShared, mappings local p = {} -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- local function trimWhitespace(s, removeBlanks) if type(s) ~= 'string' then return s end s = s:match('^%s*(.-)%s*$') if removeBlanks then if s ~= '' then return s else return nil end else return s end end -------------------------------------------------------------------------------- -- CategoryHandler class -------------------------------------------------------------------------------- local CategoryHandler = {} CategoryHandler.__index = CategoryHandler function CategoryHandler.new(data, args) local obj = setmetatable({ _data = data, _args = args }, CategoryHandler) -- Set the title object do local pagename = obj:parameter('demopage') local success, titleObj if pagename then success, titleObj = pcall(mw.title.new, pagename) end if success and titleObj then obj.title = titleObj if titleObj == mw.title.getCurrentTitle() then obj._usesCurrentTitle = true end else obj.title = mw.title.getCurrentTitle() obj._usesCurrentTitle = true end end -- Set suppression parameter values for _, key in ipairs{'nocat', 'categories'} do local value = obj:parameter(key) value = trimWhitespace(value, true) obj['_' .. key] = yesno(value) end do local subpage = obj:parameter('subpage') local category2 = obj:parameter('category2') if type(subpage) == 'string' then subpage = mw.ustring.lower(subpage) end if type(category2) == 'string' then subpage = mw.ustring.lower(category2) end obj._subpage = trimWhitespace(subpage, true) obj._category2 = trimWhitespace(category2) -- don't remove blank values end return obj end function CategoryHandler:parameter(key) local parameterNames = self._data.parameters[key] local pntype = type(parameterNames) if pntype == 'string' or pntype == 'number' then return self._args[parameterNames] elseif pntype == 'table' then for _, name in ipairs(parameterNames) do local value = self._args[name] if value ~= nil then return value end end return nil else error(string.format( 'invalid config key "%s"', tostring(key) ), 2) end end function CategoryHandler:isSuppressedByArguments() return -- See if a category suppression argument has been set. self._nocat == true or self._categories == false or ( self._category2 and self._category2 ~= self._data.category2Yes and self._category2 ~= self._data.category2Negative ) -- Check whether we are on a subpage, and see if categories are -- suppressed based on our subpage status. or self._subpage == self._data.subpageNo and self.title.isSubpage or self._subpage == self._data.subpageOnly and not self.title.isSubpage end function CategoryHandler:shouldSkipBlacklistCheck() -- Check whether the category suppression arguments indicate we -- should skip the blacklist check. return self._nocat == false or self._categories == true or self._category2 == self._data.category2Yes end function CategoryHandler:matchesBlacklist() if self._usesCurrentTitle then return self._data.currentTitleMatchesBlacklist else mShared = mShared or require('Module:Category handler/shared') return mShared.matchesBlacklist( self.title.prefixedText, mw.loadData('Module:Category handler/blacklist') ) end end function CategoryHandler:isSuppressed() -- Find if categories are suppressed by either the arguments or by -- matching the blacklist. return self:isSuppressedByArguments() or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist() end function CategoryHandler:getNamespaceParameters() if self._usesCurrentTitle then return self._data.currentTitleNamespaceParameters else if not mappings then mShared = mShared or require('Module:Category handler/shared') mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData end return mShared.getNamespaceParameters( self.title, mappings ) end end function CategoryHandler:namespaceParametersExist() -- Find whether any namespace parameters have been specified. -- We use the order "all" --> namespace params --> "other" as this is what -- the old template did. if self:parameter('all') then return true end if not mappings then mShared = mShared or require('Module:Category handler/shared') mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData end for ns, params in pairs(mappings) do for i, param in ipairs(params) do if self._args[param] then return true end end end if self:parameter('other') then return true end return false end function CategoryHandler:getCategories() local params = self:getNamespaceParameters() local nsCategory for i, param in ipairs(params) do local value = self._args[param] if value ~= nil then nsCategory = value break end end if nsCategory ~= nil or self:namespaceParametersExist() then -- Namespace parameters exist - advanced usage. if nsCategory == nil then nsCategory = self:parameter('other') end local ret = {self:parameter('all')} local numParam = tonumber(nsCategory) if numParam and numParam >= 1 and math.floor(numParam) == numParam then -- nsCategory is an integer ret[#ret + 1] = self._args[numParam] else ret[#ret + 1] = nsCategory end if #ret < 1 then return nil else return table.concat(ret) end elseif self._data.defaultNamespaces[self.title.namespace] then -- Namespace parameters don't exist, simple usage. return self._args[1] end return nil end -------------------------------------------------------------------------------- -- Exports -------------------------------------------------------------------------------- local p = {} function p._exportClasses() -- Used for testing purposes. return { CategoryHandler = CategoryHandler } end function p._main(args, data) data = data or mw.loadData('Module:Category handler/data') local handler = CategoryHandler.new(data, args) if handler:isSuppressed() then return nil end return handler:getCategories() end function p.main(frame, data) data = data or mw.loadData('Module:Category handler/data') local args = require('Module:Arguments').getArgs(frame, { wrappers = data.wrappers, valueFunc = function (k, v) v = trimWhitespace(v) if type(k) == 'number' then if v ~= '' then return v else return nil end else return v end end }) return p._main(args, data) end return p b74dd63857b24904ac452429b11213f18647471f Module:Category handler/data 828 76 168 167 2022-09-04T15:24:47Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module assembles data to be passed to [[Module:Category handler]] using -- mw.loadData. This includes the configuration data and whether the current -- page matches the title blacklist. local data = require('Module:Category handler/config') local mShared = require('Module:Category handler/shared') local blacklist = require('Module:Category handler/blacklist') local title = mw.title.getCurrentTitle() data.currentTitleMatchesBlacklist = mShared.matchesBlacklist( title.prefixedText, blacklist ) data.currentTitleNamespaceParameters = mShared.getNamespaceParameters( title, mShared.getParamMappings() ) return data abbc68048ff698e88dda06b64ecf384bbf583120 Module:Category handler/config 828 77 170 169 2022-09-04T15:24:47Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- [[Module:Category handler]] configuration data -- -- Language-specific parameter names and values can be set here. -- -- For blacklist config, see [[Module:Category handler/blacklist]]. -- -------------------------------------------------------------------------------- local cfg = {} -- Don't edit this line. -------------------------------------------------------------------------------- -- Start configuration data -- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Parameter names -- -- These configuration items specify custom parameter names. -- -- To add one extra name, you can use this format: -- -- -- -- foo = 'parameter name', -- -- -- -- To add multiple names, you can use this format: -- -- -- -- foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'}, -- -------------------------------------------------------------------------------- cfg.parameters = { -- The nocat and categories parameter suppress -- categorisation. They are used with Module:Yesno, and work as follows: -- -- cfg.nocat: -- Result of yesno() Effect -- true Categorisation is suppressed -- false Categorisation is allowed, and -- the blacklist check is skipped -- nil Categorisation is allowed -- -- cfg.categories: -- Result of yesno() Effect -- true Categorisation is allowed, and -- the blacklist check is skipped -- false Categorisation is suppressed -- nil Categorisation is allowed nocat = 'nocat', categories = 'categories', -- The parameter name for the legacy "category2" parameter. This skips the -- blacklist if set to the cfg.category2Yes value, and suppresses -- categorisation if present but equal to anything other than -- cfg.category2Yes or cfg.category2Negative. category2 = 'category2', -- cfg.subpage is the parameter name to specify how to behave on subpages. subpage = 'subpage', -- The parameter for data to return in all namespaces. all = 'all', -- The parameter name for data to return if no data is specified for the -- namespace that is detected. other = 'other', -- The parameter name used to specify a page other than the current page; -- used for testing and demonstration. demopage = 'page', } -------------------------------------------------------------------------------- -- Parameter values -- -- These are set values that can be used with certain parameters. Only one -- -- value can be specified, like this: -- -- -- -- cfg.foo = 'value name' -- -- -------------------------------------------------------------------------------- -- The following settings are used with the cfg.category2 parameter. Setting -- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2 -- is present but equal to anything other than cfg.category2Yes or -- cfg.category2Negative then it supresses cateogrisation. cfg.category2Yes = 'yes' cfg.category2Negative = '¬' -- The following settings are used with the cfg.subpage parameter. -- cfg.subpageNo is the value to specify to not categorise on subpages; -- cfg.subpageOnly is the value to specify to only categorise on subpages. cfg.subpageNo = 'no' cfg.subpageOnly = 'only' -------------------------------------------------------------------------------- -- Default namespaces -- -- This is a table of namespaces to categorise by default. The keys are the -- -- namespace numbers. -- -------------------------------------------------------------------------------- cfg.defaultNamespaces = { [ 0] = true, -- main [ 6] = true, -- file [ 12] = true, -- help [ 14] = true, -- category [100] = true, -- portal [108] = true, -- book } -------------------------------------------------------------------------------- -- Wrappers -- -- This is a wrapper template or a list of wrapper templates to be passed to -- -- [[Module:Arguments]]. -- -------------------------------------------------------------------------------- cfg.wrappers = 'Template:Category handler' -------------------------------------------------------------------------------- -- End configuration data -- -------------------------------------------------------------------------------- return cfg -- Don't edit this line. 373cd107b13a5b00e6a1b7e66a749f12502c849d Module:Category handler/shared 828 78 172 171 2022-09-04T15:24:47Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module contains shared functions used by [[Module:Category handler]] -- and its submodules. local p = {} function p.matchesBlacklist(page, blacklist) for i, pattern in ipairs(blacklist) do local match = mw.ustring.match(page, pattern) if match then return true end end return false end function p.getParamMappings(useLoadData) local dataPage = 'Module:Namespace detect/data' if useLoadData then return mw.loadData(dataPage).mappings else return require(dataPage).mappings end end function p.getNamespaceParameters(titleObj, mappings) -- We don't use title.nsText for the namespace name because it adds -- underscores. local mappingsKey if titleObj.isTalkPage then mappingsKey = 'talk' else mappingsKey = mw.site.namespaces[titleObj.namespace].name end mappingsKey = mw.ustring.lower(mappingsKey) return mappings[mappingsKey] or {} end return p d2d5de1a031e6ce97c242cbfa8afe7a92cb9eca5 Module:Category handler/blacklist 828 79 174 173 2022-09-04T15:24:48Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module contains the blacklist used by [[Module:Category handler]]. -- Pages that match Lua patterns in this list will not be categorised unless -- categorisation is explicitly requested. return { '^Main Page$', -- don't categorise the main page. -- Don't categorise the following pages or their subpages. -- "%f[/\0]" matches if the next character is "/" or the end of the string. '^Wikipedia:Cascade%-protected items%f[/\0]', '^User:UBX%f[/\0]', -- The userbox "template" space. '^User talk:UBX%f[/\0]', -- Don't categorise subpages of these pages, but allow -- categorisation of the base page. '^Wikipedia:Template index/.*$', -- Don't categorise archives. '/[aA]rchive', "^Wikipedia:Administrators' noticeboard/IncidentArchive%d+$", } 87469d7a9ef2a3c41b2bf04ae18f7c59a18fb855 Template:IPAc-en 10 80 176 175 2022-09-04T15:24:48Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:IPAc-en|main}}</includeonly><noinclude> {{documentation}} </noinclude> f81b884979df2c3ec3a7275e7fb402ad585e26e4 Module:IPAc-en 828 81 178 177 2022-09-04T15:24:49Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module implements [[Template:IPAc-en]]. local data = mw.loadData('Module:IPAc-en/data') local p = {} -- Global container for tracking categories local categoryHandler = require('Module:Category handler').main local categories = {} -- Trims whitespace from a string local function trim(s) return s:match('^%s*(.-)%s*$') end -- This implements [[Template:Nowrap]]. local function makeNowrapSpan(s) local span = mw.html.create('span') :addClass('rt-commentedText') -- Works with [[MediaWiki:Gadget-ReferenceTooltips.js]] :addClass('nowrap') :wikitext(s) return tostring(span) end local function makePronunciationText(id) id = id and string.lower(trim(id)) if id and id ~= '' and data.pronunciation[id] then return data.pronunciation[id].text end end -- This adds a tooltip icon to a label. It implements [[Template:H:title]]. local function makeTooltip(label, tooltip) local span = mw.html.create('span') :attr('title', tooltip) :wikitext(label) return tostring(span) end local function formatPhonemeGroup(phonemes) if #phonemes > 0 then local span = mw.html.create('span') :css('border-bottom', '1px dotted') :wikitext(table.concat(phonemes)) return tostring(span) else return '' end end local function renderCategories() local ret = '' if categoryHandler{ true } then ret = {} for cat in pairs(categories) do table.insert(ret, string.format('[[Category:%s]]', cat)) end table.sort(ret) ret = table.concat(ret) else ret = '' end return ret end function p._main(args) local ret = {} local i = 0 -- Keeps track of numbered args -- Pronunciation do local pron = {} while true do i = i + 1 local pronItem = makePronunciationText(args[i]) if pronItem then pron[#pron + 1] = pronItem pron[#pron + 1] = ' ' else break end end if #pron > 0 then ret[#ret + 1] = string.format( '<small>%s</small>', table.concat(pron) ) end end -- Phonemes do -- Loop through the numbered args, separating them into phoneme groups -- and separator strings (both called "words" for convenience). We only -- underline the phoneme groups, not the separators. local words = {} words[#words + 1] = '/' -- Opening slash i = i - 1 -- Set up i again as it was changed in the pronunciation loop local id repeat local phonemes = {} local isWordEnd = false while not isWordEnd do i = i + 1 id = args[i] id = id and trim(id) if not id then isWordEnd = true words[#words + 1] = formatPhonemeGroup(phonemes) elseif id ~= '' then local t = data.phonemes[id] if not t then -- We were passed an invalid id. isWordEnd = true categories["Ill-formatted IPAc-en transclusions"] = true words[#words + 1] = formatPhonemeGroup(phonemes) words[#words + 1] = makeTooltip( string.format( "<strong class=\"error\">[invalid input: '%s']</strong>", id ), 'Unrecognized symbol' ) elseif not t.label then -- The data module contains bad data, so throw an error. error(string.format( "no label was found for id '%s'", tostring(id) )) elseif t.tooltip then -- We are dealing with a regular phoneme. phonemes[#phonemes + 1] = makeTooltip( t.label, t.tooltip ) else -- We are dealing with a separator. isWordEnd = true words[#words + 1] = formatPhonemeGroup(phonemes) words[#words + 1] = t.label end end end until not id words[#words + 1] = '/' -- Closing slash -- Wrap the words in a link to IPA help. local span = mw.html.create('span') -- Suppress Navigation popups and Page Previews (aka Hovercards) :addClass('IPA nopopups noexcerpt') :attr('lang', 'en-fonipa') :wikitext(string.format( '[[Help:IPA/English|%s]]', table.concat(words) )) ret[#ret + 1] = tostring(span) end -- Audio link do local file = args.audio and trim(args.audio) if file and file ~= '' then categories["Pages including recorded pronunciations"] = true ret[#ret + 1] = mw.getCurrentFrame():expandTemplate{ title = 'Template:IPA audio link', args = { file, attribution = args.attribution } } end end -- Nowrap and categories ret = makeNowrapSpan(table.concat(ret)) .. renderCategories() -- Reset the categories table in case we are run again. categories = {} return ret end function p.main(frame) return p._main(frame:getParent().args) end return p 62c540dcdc647c5bc63614ba04eabf7f645dd284 Module:IPAc-en/data 828 82 180 179 2022-09-04T15:24:49Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module processes data for [[Module:IPAc-en]]. It is intended to be -- loaded with mw.loadData. local PRONUNCIATION_MODULE = 'Module:IPAc-en/pronunciation' local PHONEME_MODULE = 'Module:IPAc-en/phonemes' local function makeData(oldData) local newData = {} for i, old in ipairs(oldData) do local new = {} for k, v in pairs(old) do if k ~= 'aliases' and k ~= 'code' then new[k] = v end end newData[old.code] = new if old.aliases then for i, alias in ipairs(old.aliases) do newData[alias] = new end end end return newData end local function main() local pronunciation = makeData(require(PRONUNCIATION_MODULE)) local phonemes = makeData(require(PHONEME_MODULE)) -- Check that no pronunciation keys are also contained in the phonemes -- data. This would cause silent, hard-to-debug errors if it went -- unchecked, so make it cause a big red error message instead. for id in pairs(pronunciation) do if phonemes[id] then error(string.format( "duplicate ID '%s' found in %s and %s", id, PRONUNCIATION_MODULE, PHONEME_MODULE )) end end return { pronunciation = pronunciation, phonemes = phonemes, } end return main() 3428d5574793b97b1b5ba91ff0c32e0418c27642 Module:IPAc-en/pronunciation 828 83 182 181 2022-09-04T15:24:49Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module contains pronunciation-key data for [[Module:IPAc-en]]. return { { code = 'lang', text = 'English:' }, { code = 'pron', text = '' }, { code = 'local', text = 'locally' }, { code = 'ipa', text = '[[International Phonetic Alphabet|IPA]]:' }, { code = 'also', text = 'also' }, { code = 'uk', text = '[[British English|UK]]:' }, { code = 'us', text = '[[American English|US]]:' }, { code = 'uklang', text = '[[British English]]:' }, { code = 'uslang', text = '[[American English]]:' }, { code = 'ukalso', text = '[[British English|UK]] also' }, { code = 'usalso', text = '[[American English|US]] also' }, { code = 'alsouk', text = 'also [[British English|UK]]:' }, { code = 'alsous', text = 'also [[American English|US]]:' }, } f4b022e065c591350dd1ee03942c104a3a096395 Module:IPAc-en/phonemes 828 84 184 183 2022-09-04T15:24:50Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module contains phoneme data for [[Module:IPAc-en]]. return { -- CONSONANTS { code = "b", label = "b", tooltip = "'b' in 'buy'", }, { code = "d", label = "d", tooltip = "'d' in 'dye'", }, { code = "dj", aliases = {"dy", "dʲ"}, label = "dj", tooltip = "/dj/: 'd' in 'dew'", }, { code = "dʒ", aliases = {"dZ", "ʤ"}, label = "dʒ", tooltip = "/dʒ/: 'j' in 'jam'", }, { code = "ð", aliases = {"D"}, label = "ð", tooltip = "/ð/: 'th' in 'this'", }, { code = "f", label = "f", tooltip = "'f' in 'find'", }, { code = "ɡ", aliases = {"g"}, label = "ɡ", tooltip = "/ɡ/: 'g' in 'guy'", }, { code = "h", label = "h", tooltip = "'h' in 'hi'", }, { code = "hw", aliases = {"ʍ"}, label = "hw", tooltip = "/hw/: 'wh' in 'why'", }, { code = "j", aliases = {"y"}, label = "j", tooltip = "/j/: 'y' in 'yes'", }, { code = "k", label = "k", tooltip = "'k' in 'kind'", }, { code = "l", label = "l", tooltip = "'l' in 'lie'", }, { code = "lj", aliases = {"ly", "lʲ"}, label = "lj", tooltip = "/lj/: 'l' in 'lute'", }, { code = "m", label = "m", tooltip = "'m' in 'my'", }, { code = "n", label = "n", tooltip = "'n' in 'nigh'", }, { code = "nj", aliases = {"ny", "nʲ"}, label = "nj", tooltip = "/nj/: 'n' in 'new'", }, { code = "ŋ", aliases = {"N", "ng"}, label = "ŋ", tooltip = "/ŋ/: 'ng' in 'sing'", }, { code = "p", label = "p", tooltip = "'p' in 'pie'", }, { code = "r", aliases = {"ɹ", "ɻ"}, label = "r", tooltip = "'r' in 'rye'", }, { code = "s", label = "s", tooltip = "'s' in 'sigh'", }, { code = "sj", aliases = {"sy", "sʲ"}, label = "sj", tooltip = "/sj/: 's' in 'consume'", }, { code = "ʃ", aliases = {"S", "sh"}, label = "ʃ", tooltip = "/ʃ/: 'sh' in 'shy'", }, { code = "t", label = "t", tooltip = "'t' in 'tie'", }, { code = "tj", aliases = {"ty", "tʲ"}, label = "tj", tooltip = "/tj/: 't' in 'tune'", }, { code = "tʃ", aliases = {"tS", "ʧ", "ch"}, label = "tʃ", tooltip = "/tʃ/: 'ch' in 'China'", }, { code = "θ", aliases = {"T"}, label = "θ", tooltip = "/θ/: 'th' in 'thigh'", }, { code = "θj", aliases = {"θy", "θʲ"}, label = "θj", tooltip = "/θj/: 'th' in 'enthuse'", }, { code = "v", label = "v", tooltip = "'v' in 'vie'", }, { code = "w", label = "w", tooltip = "'w' in 'wind'", }, { code = "z", label = "z", tooltip = "'z' in 'zoom'", }, { code = "zj", aliases = {"zy", "zʲ"}, label = "zj", tooltip = "/zj/: 'Z' in 'Zeus'", }, { code = "ʒ", aliases = {"Z", "zh"}, label = "ʒ", tooltip = "/ʒ/: 's' in 'pleasure'", }, -- VOWELS { code = "ɑː", aliases = {"A:", "ɑ:", "aː", "a:"}, label = "ɑː", tooltip = "/ɑː/: 'a' in 'father'", }, { code = "ɑːr", aliases = {"ɑɹ", "aːr", "a:r", "ɑ:r", "ɑr"}, label = "ɑːr", tooltip = "/ɑːr/: 'ar' in 'far'", }, { code = "ɒ", aliases = {"Q"}, label = "ɒ", tooltip = "/ɒ/: 'o' in 'body'", }, { code = "ɒr", aliases = {"Qr"}, label = "ɒr", tooltip = "/ɒr/: 'or' in 'moral'", }, { code = "æ", aliases = {"ae", "{"}, label = "æ", tooltip = "/æ/: 'a' in 'bad'", }, { code = "ær", aliases = {"aer", "&r", "æɹ"}, label = "ær", tooltip = "/ær/: 'arr' in 'marry'", }, { code = "aɪ", aliases = {"ai", "aI"}, label = "aɪ", tooltip = "/aɪ/: 'i' in 'tide'", }, { code = "aɪər", aliases = {"aɪr", "aIr", "aɪə"}, label = "aɪər", tooltip = "/aɪər/: 'ire' in 'fire'", }, { code = "aʊ", aliases = {"au", "aU"}, label = "aʊ", tooltip = "/aʊ/: 'ou' in 'mouth'", }, { code = "aʊər", aliases = {"aʊr", "aUr", "aʊə", "aur"}, label = "aʊər", tooltip = "/aʊər/: 'our' in 'hour'", }, { code = "ɛ", aliases = {"E"}, label = "ɛ", tooltip = "/ɛ/: 'e' in 'dress'", }, { code = "ɛr", aliases = {"Er"}, label = "ɛr", tooltip = "/ɛr/: 'err' in 'merry'", }, { code = "eɪ", aliases = {"ei", "eI", "eː", "e:"}, label = "eɪ", tooltip = "/eɪ/: 'a' in 'face'", }, { code = "ɛər", aliases = {"eir", "eIr", "e@r", "E@r", "ɛɪɹ", "eɪr", "eːr", "e:r", "ɛəɹ", "ɛə", "ɛːr", "ɛ:r", "ɛː", "ɛ:", "E:", "E:r"}, label = "ɛər", tooltip = "/ɛər/: 'are' in 'bare'", }, { code = "ɛəˈr", aliases = {"ɛə'r", "eəˈr", "eə'r", "e@'r", "E@'r", "ɛːˈr", "E:'r"}, label = "ɛəˈr", tooltip = "/ɛəˈr/: 'ere' in 'thereof'", }, { code = "ɛəˌr", aliases = {"ɛə,r", "eəˌr", "eə,r", "E@,r", "E@%r", "e@,r", "e@%r", "ɛːˌr", "E:,r", "E:%r"}, label = "ɛəˌr", tooltip = "/ɛəˌr/: 'ere' in 'thereof'", }, { code = "ɪ", aliases = {"I", "ᵻ"}, label = "ɪ", tooltip = "/ɪ/: 'i' in 'kit'", }, { code = "ɪr", label = "ɪr", tooltip = "/ɪr/: 'irr' in 'mirror'", }, { code = "iː", aliases = {"i:"}, label = "iː", tooltip = "/iː/: 'ee' in 'fleece'", }, { code = "ɪər", aliases = {"i:r", "iːr", "I@r", "i@r", "ɪəɹ", "iːɹ", "ɪə"}, label = "ɪər", tooltip = "/ɪər/: 'ear' in 'near'", }, { code = "ɪəˈr", aliases = {"ɪə'r", "I@'r"}, label = "ɪəˈr", tooltip = "/ɪəˈr/: 'er' in 'spheroidal'", }, { code = "ɪəˌr", aliases = {"ɪə,r", "I@,r", "I@%r"}, label = "ɪəˌr", tooltip = "/ɪəˌr/: 'er' in 'spheroidal'", }, { code = "oʊ", aliases = {"o:", "oː", "ou", "oU", "@u", "@U", "əʊ", "əu", "oʊ-"}, label = "oʊ", tooltip = "/oʊ/: 'o' in 'code'", }, { code = "ɔː", aliases = {"O", "O:", "ɔ:", "ɒː", "Q:"}, label = "ɔː", tooltip = "/ɔː/: 'au' in 'fraud'", }, { code = "ɔːr", aliases = {"Or", "ɔɹ", "ɔ(r)", "ɔr", "ɔər", "oUr", "ɔəɹ", "ɔʊɹ", "oʊɹ", "oʊr", "oːr", "o:r", "ɔə", "ɔə(r)"}, label = "ɔːr", tooltip = "/ɔːr/: 'ar' in 'war'", }, { code = "ɔɪ", aliases = {"oj", "ɔj", "oi", "oɪ", "ɔi", "OI", "oy"}, label = "ɔɪ", tooltip = "/ɔɪ/: 'oi' in 'choice'", }, { code = "ɔɪər", aliases = {"ɔɪr", "oyr", "ɔɪə"}, label = "ɔɪər", tooltip = "/ɔɪər/: 'oir' in 'coir'", }, { code = "ʊ", aliases = {"U", "ᵿ"}, label = "ʊ", tooltip = "/ʊ/: 'u' in 'push'", }, { code = "ʊr", aliases = {"Ur"}, label = "ʊr", tooltip = "/ʊr/: 'our' in 'courier'", }, { code = "uː", aliases = {"u:"}, label = "uː", tooltip = "/uː/: 'oo' in 'goose'", }, { code = "ʊər", aliases = {"u:r", "uːr", "u@r", "U@r", "ʊəɹ", "ʊə"}, label = "ʊər", tooltip = "/ʊər/: 'our' in 'tour'", }, { code = "ʊəˈr", aliases = {"ʊə'r", "U@'r"}, label = "ʊəˈr", tooltip = "/ʊəˈr/: 'ur' in 'plurality'", }, { code = "ʊəˌr", aliases = {"ʊə,r", "U@,r", "U@%r"}, label = "ʊəˌr", tooltip = "/ʊəˌr/: 'ur' in 'plurality'", }, { code = "ʌ", aliases = {"V"}, label = "ʌ", tooltip = "/ʌ/: 'u' in 'cut'", }, { code = "ʌr", aliases = {"Vr", "ʌɹ"}, label = "ʌr", tooltip = "/ʌr/: 'urr' in 'hurry'", }, { code = "ɜːr", aliases = {"ɝː", "ɝ", "3r", "3:r", "əːr", "@:r", "ɜɹ", "ɜ(r)", "ɜr"}, label = "ɜːr", tooltip = "/ɜːr/: 'ur' in 'fur'", }, { code = "ə", aliases = {"@"}, label = "ə", tooltip = "/ə/: 'a' in 'about'", }, -- SYLLABIC CONSONANTS { code = "ər", aliases = {"ɚ", "@r", "əɹ", "ə(r)"}, label = "ər", tooltip = "/ər/: 'er' in 'letter'", }, { code = "əl", aliases = {"@l", "ᵊl", "l̩"}, label = "əl", tooltip = "/əl/: 'le' in 'bottle'", }, { code = "ən", aliases = {"@n", "ᵊn", "n̩"}, label = "ən", tooltip = "/ən/: 'on' in 'button'", }, { code = "əm", aliases = {"@m", "ᵊm", "m̩"}, label = "əm", tooltip = "/əm/: 'm' in 'rhythm'", }, -- ARCHIPHONEMES { code = "i", label = "i", tooltip = "/i/: 'y' in 'happy'", }, { code = "u", label = "u", tooltip = "/u/: 'u' in 'influence'", }, -- MARGINAL SEGMENTS { code = "x", label = "x", aliases = {"kh"}, tooltip = "/x/: 'ch' in 'loch'", }, { code = "ʔ", aliases = {"?"}, label = "ʔ", tooltip = "/ʔ/: the catch in 'uh-oh'", }, { code = "ɒ̃", aliases = {"ɑ̃", "ɒ~", "ɑ~", "Q~"}, label = "ɒ̃", tooltip = "/ɒ̃/: nasal 'an' in 'vin blanc'", }, { code = "æ̃", aliases = {"ae~", "{~", "ã", "a~"}, label = "æ̃", tooltip = "/æ̃/: nasal 'in' in 'vin blanc'", }, { code = "ɜː", aliases = {"3", "3:", "ɜ:", "ɜ", "əː", "@:"}, label = "ɜː", tooltip = "/ɜː/: r-less 'ur' in 'nurse'", }, -- SUPRASEGMENTALS { code = "ˈ", aliases = {"'", '"'}, label = "ˈ", tooltip = "/ˈ/: primary stress follows", }, { code = "ˌ", aliases = {",", "%"}, label = "ˌ", tooltip = "/ˌ/: secondary stress follows", }, { code = ".", aliases = {"·"}, label = ".", tooltip = "/./: syllable break", }, { code = "#", label = "#", tooltip = "/#/: morpheme break", }, { code = "!", label = "&#124;", tooltip = "/|/: prosodic break (minor)", }, { code = "!!", aliases = {"‖"}, label = "‖", tooltip = "/‖/: prosodic break (major)", }, -- SEPARATORS -- Tables without tooltip text are used as word separators. In addition to -- not having any tooltip text in the template output, they are not -- underlined. { code = "_", label = "<span class=\"wrap\"> </span>", }, { code = "nbsp", aliases = {"&nbsp;"}, label = " ", }, { code = ",_", label = ",<span class=\"wrap\"> </span>", }, { code = "-", aliases = {"–"}, label = "-", }, { code = "(", label = "(", }, { code = ")", label = ")", }, -- This is useful for highly variable words in place names, which are not -- important to transcribe. { code = "...", label = "&thinsp;...<span class=\"wrap\">&thinsp;</span>", }, -- Obsolete combinations, kept for compatibility { code = "juː", label = "juː", tooltip = "/juː/: 'u' in 'cute'", }, { code = "jʊər", label = "jʊər", tooltip = "/jʊər/: 'ure' in 'cure'", }, } edb55389474ac8485fc15b3386eebeb0c44b7263 Template:Cite web 10 85 186 185 2022-09-04T15:24:50Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=web }}</includeonly><noinclude> {{documentation}} </noinclude> ea1b0f38afd9728a1cf9f2e3f540887a402fab8e Module:Portal/images/s 828 86 188 187 2022-09-04T15:24:51Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[==[ This is the "S" list of portal image names. It contains a list of portal images for use with [[Module:Portal]] -- for portal names that start with the letter "S". For aliases to existing portal names, and for portal names that -- start with other letters, please use the appropriate page from the following list: -- [[Module:Portal/images/a]] - for portal names beginning with "A". -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/o]] - for portal names beginning with "O". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- [[Module:Portal/images/aliases]] - for adding aliases for existing portal names. Use this page for variations -- in spelling and diacritics, etc., no matter what letter the portal begins with. -- When adding entries, please use alphabetical order. The format of the images table entries is as follows: -- ["portal name"] = "image.svg", -- The portal name should be the name of your portal, in lower case. For example, the portal name for -- "Portal:United Kingdom" would be "united kingdom". The image name should be capitalised normally, and the "File:" -- namespace prefix should be omitted. ]==] return { ["saarc"] = "SAARC 1717549468.png|link=|alt=icon", ["saarland"] = "Flag of Saarland.svg|border|link=|alt=flag", ["saba"] = "Flag of Saba.svg|border|link=|alt=flag", ["sabah"] = "Flag of Sabah.svg|border|link=|alt=flag", ["sacred christian music"] = "Musical note nicu bucule 01.svg|link=|alt=icon", ["saguenay–lac-saint-jean"] = "Flag of Saguenay-Lac-Saint-Jean.svg|border|link=|alt=flag", ["sailing"] = "Sailing pictogram.svg|link=|alt=", ["saint barthelemy"] = "Flag of Saint Barthelemy (local).svg|border|link=|alt=flag", ["saint helena, ascension and tristan da cunha"] = "Flag of Saint Helena.svg|border|link=|alt=flag", ["saint kitts and nevis"] = "Flag of Saint Kitts and Nevis.svg|border|link=|alt=flag", ["saint lucia"] = "Flag of Saint Lucia.svg|border|link=|alt=flag", ["saint martin"] = "Flag of Saint Martin.png|border|link=|alt=flag", ["saint petersburg"] = "Flag of Saint Petersburg Russia.svg|alt=flag", ["saint pierre and miquelon"] = "Flag of Saint-Pierre and Miquelon.svg|border|link=|alt=flag", ["saint vincent and the grenadines"] = "Flag of Saint Vincent and the Grenadines.svg|border|link=|alt=flag", ["saints"] = "Gloriole blur.svg|link=|alt=", ["salad dressing"] = "Ranch dressing.jpg|link=|alt=", ["salmon"] = "Alaska salmon.jpg|link=|alt=", ["samoa"] = "Flag of Samoa.svg|border|link=|alt=flag", ["san antonio"] = "Coat of arms of San Antonio.svg|link=|alt=arms", ["san diego"] = "San Diego,California,USA. - panoramio (139).jpg|link=|alt=photo", ["san diego county"] = "Seal of San Diego County, California.png|link=|alt=seal", ["san diego–tijuana"] = "San Diego-Tijuana JPLLandsat.jpg|border|link=|alt=flag", ["sandwich"] = "Sandwich (1).jpg|link=|alt=", ["san francisco bay area"] = "SF From Marin Highlands3.jpg|border|link=|alt=", ["san francisco neighborhoods"] = "Columbus and Broadway (8219737166).jpg|link=|alt=", ["san luis potosí"] = "Flag of San Luis Potosi.svg|border|link=|alt=flag", ["san marino"] = "Flag of San Marino.svg|border|link=|alt=flag", ["santa barbara county"] = "Seal of Santa Barbara County, California.png|link=|alt=seal", ["santana"] = "Carlos Santana 2005.jpg|link=|alt=", ["santiago, chile"] = "Flag of Santiago de Chile.svg|alt=flag", ["são tomé and príncipe"] = "Flag of Sao Tome and Principe.svg|border|link=|alt=flag", ["são paulo"] = "Bandeira da cidade de São Paulo.svg|link=|alt=", ["salad"] = "Composed salad.jpg|link=|alt=", ["salads"] = "Composed salad.jpg|link=|alt=", ["salt"] = "Keukenzout (NaCl), onder de microscoop.jpg|link=|alt=", ["santiago"] = "Flag of Santiago de Chile.svg|alt=flag", ["sarajevo"] = "Flag of Sarajevo.svg|alt=flag", ["sarawak"] = "Flag of Sarawak.svg|border|link=|alt=flag", ["sasanian empire"] = "Derafsh Kaviani flag of the late Sassanid Empire.svg|border|link=|alt=flag", ["saskatchewan"] = "Flag of Saskatchewan.svg|border|link=|alt=flag", ["saskatchewan communities and neighbourhoods"] = "Flag-map of Saskatchewan.svg|link=|alt=map", ["saturn"] = "Saturn - April 25 2016 (24102807868).png|link=|alt=", ["saudi arabia"] = "Flag of Saudi Arabia.svg|border|link=|alt=flag", ["sausage"] = "Saucisses.svg|link=|alt=", ["sausages"] = "Saucisses.svg|link=|alt=", ["saxony"] = "Flag of Saxony.svg|border|link=|alt=flag", ["saxony-anhalt"] = "Flag of Saxony-Anhalt (state).svg|border|link=|alt=flag", ["schleswig-holstein"] = "Flag of Schleswig-Holstein (state).svg|border|link=|alt=flag", ["schools"] = "School.svg|link=|alt=icon", ["science"] = "Nuvola apps kalzium.svg|alt=icon", ["science and academia"] = "Rachel Carson w (cropped).jpg|link=|alt=photo", ["science fiction"] = "Sf-userbox.png|alt=icon", ["scientology"] = "Scientology e meter blue.jpg|alt=icon", ["scifi"] = "Sf-userbox.png|alt=icon", ["scotland"] = "Flag of Scotland.svg|border|link=|alt=flag", ["scottish islands"] = "ScottishIsles.jpg|link=|alt=map", ["scouting"] = "WikiProject Scouting fleur-de-lis dark.svg|alt=icon", ["sculpture"] = "Noun Project - Sculpture.svg|alt=", ["seafood"] = "Crab-icon.png|link=|alt=", ["seamounts"] = "Seamount.svg|link=|alt=", ["seattle"] = "SpaceNeedleTopClose.jpg|alt=icon", ["sega"] = "SEGA logo.svg|link=|alt=", ["senegal"] = "Flag of Senegal.svg|border|link=|alt=flag", ["selangor"] = "Flag of Selangor.svg|alt=flag", ["seoul"] = "Seal of Seoul.svg|link=|alt=seal", ["september 11 attacks"] = "Y24-Wtc-september-5.jpg|alt=icon", ["serbia"] = "Flag of Serbia.svg|border|link=|alt=flag", ["serbian cuisine"] = "Ćevapčići.jpg|link=|alt=", ["serer people"] = "Serer Royal War Drum (Jung-Jung). 19th Century. Jung-Jung From The Kingdom of Sine (in modern day Senegal).jpg|alt=icon", ["serer religion"] = "Five Pointed Star Lined.svg|link=|alt=", ["set theory"] = "Venn0001.svg|link=|alt=", ["seton hall university"] = "Shu logo.png|link=|alt=logo", ["seventh-day adventist church"] = "James and Ellen White.jpg|link=|alt=", ["severe weather"] = "Marquette, Kansas EF4 tornado on April 14, 2012.png|link=|alt=icon", ["sexuality"] = "Bisexuality symbol (bold, color).svg|alt=icon", ["sex work"] = "Umbrella-159361.svg|link=|alt=", ["seychelles"] = "Flag of Seychelles.svg|border|link=|alt=flag", ["sf"] = "Dragon-149393.svg|alt=icon", ["sfpeople"] = "Dragon-149393.svg|alt=icon", ["sfpubs"] = "Dragon-149393.svg|alt=icon", ["shakespeare"] = "Shakespeare (oval-cropped).png|link=|alt=", ["shakira"] = "S by shakira logo.png|alt=icon", ["shanghai"] = "Shanghainame.png|link=|alt=", ["shania twain"] = "Shania Twain Portrait.jpg|alt=icon", ["sharjah"] = "Flag of Sharjah.svg|border|link=|alt=flag", ["sharks"] = "Greyreefsharksmall2.jpg|alt=icon", ["shenzhen"] = "Shenzhen in Chinese.png|alt=Shenzhen", ["shia islam"] = "Ghadir logo.png|alt=icon", ["shinto"] = "Shinto torii icon vermillion.svg|link=|alt=", ["shreveport"] = "Shreveport-City-Flag.png|border|link=|alt=flag", ["shreya ghoshal"] = "Shreya at concert.jpg|alt=icon", ["shropshire"] = "Flag of Shropshire.svg|alt=flag|link=", ["siberia"] = "Kuznetsk Alatau 3.jpg|border|link=|alt=", ["sierra leone"] = "Flag of Sierra Leone.svg|border|link=|alt=flag", ["sikhism"] = "Khanda emblem.svg|link=|alt=", ["sikkim"] = "Seal of Sikkim color.png|link=|alt=seal", ["silent film"] = "Video-x-generic.svg|link=|alt=", ["silesia"] = "Silesia Inferior COA.svg|alt=icon", ["sinaloa"] = "Flag of Sinaloa.svg|border|link=|alt=flag", ["sindh"] = "Flag of Sindh.svg|border|link=|alt=flag", ["singapore"] = "Flag of Singapore.svg|border|link=|alt=flag", ["sint eustatius"] = "Flag of Sint Eustatius.svg|border|link=|alt=flag", ["sint maarten"] = "Flag of Sint Maarten.svg|border|link=|alt=flag", ["slavery"] = "IJzeren voetring voor gevangenen transparent background.png|border|link=|alt=icon", ["slipknot"] = "SlipknotProject.png|alt=icon", ["slovak republic"] = "Flag of Slovakia.svg|border|link=|alt=flag", ["slovakia"] = "Flag of Slovakia.svg|border|link=|alt=flag", ["slovenia"] = "Flag of Slovenia.svg|border|link=|alt=flag", ["sm entertainment"] = "SM Entertainment Logo.svg|link=|alt=", ["snakes"] = "Snake icon.svg|link=|alt=", ["snk"] = "SNK Playmore logo and wordmark.png|link=|alt=", ["snooker"] = "Snooker balls triangled.png|alt=icon", ["soap operas and telenovelas"] = "Drama-icon.svg|alt=icon", ["soccer in the united states"] = "Soccerball USA.png|link=|alt=", ["social and political philosophy"] = "P derecho.svg|link=|alt=", ["social movements"] = "Peace sign.svg|link=|alt=", ["social science"] = "P social sciences-lightblue.png|link=|alt=icon", ["social sciences"] = "DrustveneNauke.png|alt=icon", ["social welfare and social work"] = "Vista Login Manager Cropped.svg|alt=icon", ["socialism"] = "Red flag II.svg|alt=icon", ["society"] = "Social sciences.svg|alt=icon", ["sociology"] = "Logo sociology.svg|link=|alt=", ["soft drinks"] = "Soft Drink.svg|link=|alt=", ["software"] = "Crystal Clear device cdrom unmount.png|alt=icon", ["software testing"] = "Green bug and broom.svg|alt=icon", ["solar system"] = "Solar system.jpg|link=|alt=", ["solomon islands"] = "Flag of Solomon Islands.svg|border|link=|alt=flag", ["somalia"] = "Flag of Somalia.svg|border|link=|alt=flag", ["somaliland"] = "Flag of Somaliland.svg|border|link=|alt=flag", ["somerset"] = "Somerset shield.png|alt=icon", ["sonic"] = "Chaos emeralds.svg|alt=icon", ["sonora"] = "Flag of Sonora.svg|border|link=|alt=flag", ["sony"] = "Sony logo.svg|link=|alt=", ["sony playstation"] = "PS3-slim-console.png|link=|alt=", ["soup"] = "Shrimp and corn chowder.jpg|link=|alt=", ["soups"] = "Shrimp and corn chowder.jpg|link=|alt=", ["south africa"] = "Flag of South Africa.svg|border|link=|alt=flag", ["south america"] = "South America (orthographic projection).svg|link=|alt=map", ["south asia"] = "India 78.40398E 20.74980N.jpg|link=|alt=", ["south australia"] = "Flag of South Australia.svg|border|link=|alt=flag", ["south carolina"] = "Flag of South Carolina.svg|border|link=|alt=flag", ["south dakota"] = "Flag of South Dakota.svg|border|link=|alt=flag", ["south east england"] = "EnglandSouthEast.png|alt=icon", ["south georgia and the south sandwich islands"] = "Flag of South Georgia and the South Sandwich Islands.svg|border|link=|alt=flag", ["south korea"] = "Flag of South Korea.svg|border|link=|alt=flag", ["south park"] = "South Park sign logo.png|link=|alt=", ["south sudan"] = "Flag of South Sudan.svg|border|link=|alt=flag", ["southeast asia"] = "Location Southeast Asia.svg|link=|alt=", ["southern california"] = "USA California Southern location map.svg|link=|alt=map", ["southwest asia"] = "Southwest-Asia-map.PNG|link=|alt=", ["soviet union"] = "Flag of the Soviet Union.svg|border|link=|alt=flag", ["soy"] = "CSIRO ScienceImage 3273 Soybeans.jpg|link=|alt=", ["space"] = "Earth-moon.jpg|link=|alt=", ["spaceflight"] = "RocketSunIcon.svg|link=|alt=", ["spain"] = "Flag of Spain.svg|border|link=|alt=flag", ["spanish american wars of independence"] = "Red versus blue swords.svg|alt=icon", ["special operations"] = "APP-6 Special Operations Forces.svg|link=|alt=", ["speculative fiction"] = "Dragon-149393.svg|alt=icon", ["speculative fiction/fantasy"] = "Masked man.svg|link=|alt=icon", ["speculative fiction/horror"] = "Vampire Smiley.png|alt=icon", ["speculative fiction/people"] = "Dragon-149393.svg|alt=icon", ["speculative fiction/publications"] = "Dragon-149393.svg|alt=icon", ["spices"] = "Thymus vulgaris.jpg|link=|alt=icon", ["spirituality"] = "EndlessKnot03d.png|link=|alt=", ["spongebob squarepants"] = "WikiProject SpongeBob logo - Logo.svg|alt=icon", ["sports"] = "Sports icon.png|link=|alt=", ["sports and games"] = "Sports and games.png|alt=icon", ["sports in canada"] = "Flag shirt of Canada.png|alt=icon", ["sport of athletics"] = "Roman bronze copy of Myron’s Discobolos, 2nd century CE (Glyptothek Munich).jpg|link=|alt=", ["sri lanka"] = "Flag of Sri Lanka.svg|border|link=|alt=flag", ["sri lankan cuisine"] = "Kiribath (milk rice).jpg|link=|alt=", ["st. john's, newfoundland and labrador"] = "City of St. John's.jpg|link=|alt=", ["st. louis"] = "Flag of St. Louis, Missouri.svg|border|link=|alt=flag", ["staffordshire"] = "Staffordshire Flag.svg|border|link=|alt=flag", ["stamford"] = "Stamford town crest.png|link=|alt=crest", ["stanford university"] = "Stanford logo.png|link=|alt=logo", ["star"] = "He1523a.jpg|alt=icon", ["stars"] = "He1523a.jpg|alt=icon", ["star trek"] = "Delta-shield.svg|link=|alt=", ["star wars"] = "Lightsaber blue.svg|link=|alt=", ["state of georgia"] = "Flag of Georgia (U.S. state).svg|border|link=|alt=flag", ["state of mexico"] = "Flag of Mexico (state).png|border|link=|alt=flag", ["state university of new york"] = "SUNY brandmark.svg|link=|alt=brandmark", ["state university system of florida"] = "SUSF Locations.jpg|link=|alt=map", ["statistics"] = "Fisher iris versicolor sepalwidth.svg|alt=icon", ["statue of liberty"] = "FREEDOM FOR ALL!.jpg|alt=", ["steampunk"] = "Steampunk-falksen.jpg|alt=icon", ["stockholm"] = "Flag of Stockholm.svg|alt=flag", ["strategy games"] = "Chess.svg|alt=icon", ["strawberries"] = "FraiseFruitPhoto.jpg|link=|alt=", ["strawberry"] = "FraiseFruitPhoto.jpg|link=|alt=", ["street food"] = "Food Truck - The Noun Project.svg|link=|alt=", ["street foods"] = "Food Truck - The Noun Project.svg|link=|alt=", ["submarine"] = "Submarine.svg|alt=icon", ["submarines"] = "Submarine.svg|alt=icon", ["sudan"] = "Flag of Sudan.svg|border|link=|alt=flag", ["sufism"] = "Soefi symbool.gif|link=|alt=", ["super bowl"] = "Lombardi Trophy.png|link=|alt=", ["superfunds"] = "Superfund sites.svg|link=|alt=map", ["superhero fiction"] = "Question bubble thing.svg|link=|alt=", ["supermarket"] = "ShoppingCart.svg|link=|alt=", ["supermarkets"] = "ShoppingCart.svg|link=|alt=", ["supreme court of the united states"] = "Supreme Court.jpg|link=|alt=", ["surat"] = "Surat at night.JPG|link=|alt=photo", ["surfing"] = "Pictograms-nps-water-surfing.svg|link=|alt=", ["suriname"] = "Flag of Suriname.svg|border|link=|alt=flag", ["surrey"] = "EnglandSurrey.png|alt=icon", ["sushi"] = "Emojione 1F363.svg|border|link=|alt=", ["sustainability"] = "Nested sustainability-v2.svg|border|link=|alt=", ["sussex"] = "SussexBrit5.PNG|link=|alt=", ["sustainable development"] = "Sustainable development.svg|alt=icon", ["sweden"] = "Flag of Sweden.svg|border|link=|alt=flag", ["swimming"] = "Swimming pictogram.svg|link=|alt=", ["switzerland"] = "Flag of Switzerland.svg|border|link=|alt=flag", ["sydney"] = "Sydney COA.gif|alt=icon", ["syracuse, new york"] = "SyracuseSkyline01.JPG|link=|alt=", ["syria"] = "Flag of Syria.svg|border|link=|alt=flag", ["syriac christianity"] = "Bible and Pulpit, Mor Hananyo.jpg|alt=icon", ["syriac"] = "Syriac Sertâ book script.jpg|link=|alt=", ["syrian civil war"] = "Flag of Syria (2011 combined).svg|border|link=|alt=flag", ["systems"] = "Complex-adaptive-system.jpg|link=|alt=diagram", ["systems engineering initiative"] = "Systems Engineering Process II.gif|link=|alt=diagram", ["systems science"] = "Complex-adaptive-system.jpg|link=|alt=diagram" } a240880fd11e77e94cd6091361c41c9fdf8e85df Template:Reflist 10 87 190 189 2022-09-04T15:24:51Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <templatestyles src="Reflist/styles.css" /><div class="reflist <!-- -->{{#if:{{{1|}}}{{{colwidth|}}}|reflist-columns references-column-width}} <!-- -->{{#switch:{{{liststyle|{{{group|}}}}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=reflist-{{{liststyle|{{{group}}}}}}}} <!-- -->{{#if:{{{1|}}}|{{#iferror:{{#ifexpr: {{{1|1}}} > 1 }}||{{#switch:{{{1|}}}|1=|2=reflist-columns-2|#default=reflist-columns-3}} }}}}" <!-- end class -->{{#if: {{{1|}}}<!-- start style --> | {{#iferror: {{#ifexpr: {{{1|1}}} > 1 }} |style="column-width: {{{1}}};"}} | {{#if: {{{colwidth|}}}|style="column-width: {{{colwidth}}};"}} }}> {{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive={{#if:{{{1|}}}{{{colwidth|}}}|0|1}}}}</div>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using reflist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Reflist]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | colwidth | group | liststyle | refs }}<noinclude> {{Documentation}} </noinclude> 8c65cc88272db6c0f5cf2b49f84d3e460e60ee5f Template:Reflist/styles.css 10 88 192 191 2022-09-04T15:24:51Z SpaceMan 2 1 revision imported: Canopus text text/plain /* {{pp|small=yes}} */ /* can we remove the font size declarations? .references gets a font-size in * common.css that is always 90, and there is nothing else in reflist out in * the wild. May affect column sizes. */ .reflist { font-size: 90%; /* Default font-size */ margin-bottom: 0.5em; list-style-type: decimal; } .reflist .references { font-size: 100%; /* Reset font-size when nested in div.reflist */ margin-bottom: 0; /* Avoid double margin when nested in div.reflist */ list-style-type: inherit; /* Enable custom list style types */ } /* columns-2 and columns-3 are legacy for "2 or more" column view from when the * template was implemented with column-count. */ .reflist-columns-2 { column-width: 30em; } .reflist-columns-3 { column-width: 25em; } /* Reset top margin for lists embedded in columns */ .reflist-columns { margin-top: 0.3em; } .reflist-columns ol { margin-top: 0; } /* Avoid elements breaking between columns */ .reflist-columns li { page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */ break-inside: avoid-column; } .reflist-upper-alpha { list-style-type: upper-alpha; } .reflist-upper-roman { list-style-type: upper-roman; } .reflist-lower-alpha { list-style-type: lower-alpha; } .reflist-lower-greek { list-style-type: lower-greek; } .reflist-lower-roman { list-style-type: lower-roman; } 531a26d48f0e7826c61f764cfb7d5fb200032c34 Template:Clear 10 89 194 193 2022-09-04T15:24:52Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <div style="clear:{{{1|both}}};"></div><noinclude> {{documentation}} </noinclude> 38bab3e3d7fbd3d6800d46556e60bc6bac494d72 Template:Authority control 10 90 196 195 2022-09-04T15:24:52Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#invoke:Authority control|authorityControl}}<noinclude>{{Documentation}}</noinclude><includeonly><noinclude> </noinclude>{{#switch:{{NAMESPACE}}||{{ns:14}}=<noinclude> Only articles and categories. </noinclude>{{#invoke:Check for unknown parameters|check|arts|state|extralist|ignoreblank=1|showblankpositional=1|unknown=[[Category:Pages using authority control with parameters|_VALUE_]]|preview=Page using [[Template:Authority control]] with "_VALUE_", please move this to Wikidata if possible}} }}</includeonly> e90b2d4067a752dad843f562fc9e4114bf560c8a Module:Authority control 828 91 198 197 2022-09-04T15:24:53Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain require('Module:No globals') local p = {} local title = mw.title.getCurrentTitle() local namespace = title.namespace local testcases = (string.sub(title.subpageText,1,9) == 'testcases') --[[==========================================================================]] --[[ Category functions ]] --[[==========================================================================]] local function addCat( cat ) if cat and cat ~= '' then return '[[Category:'..cat..']]'..p.redCatLink(cat) end return '' end function p.getCatForId( id ) local cat = '' if namespace == 0 then cat = 'Articles with '..id..' identifiers' end return addCat(cat) end function p.redCatLink( cat ) --cat == 'Blah' (not 'Category:Blah', not '[[Category:Blah]]') if cat and cat ~= '' and testcases == false and mw.title.new(cat, 14).exists == false then return '[[Category:Pages with red-linked authority control categories]]' end return '' end function p.createRow( id, rawValues, link, links, withUid, specialCat, prefix) local faultyCat = 'Articles with faulty '..(specialCat or id)..' identifiers' if links then -- all links[] use withUid = false; no check needed local row = '' if prefix then row = row..'*'..prefix end for i, l in ipairs( links ) do if i == 1 and not prefix then row = row..'*' else row = row..'\n**' end if l then row = row..'<span class="uid">'..l..'</span>' else row = row..'<span class="error">The '..id..' id '..rawValues[i]..' is not valid.</span>'..addCat(faultyCat) end end return row..'\n' elseif link then -- All IDs that have a prefix support multiple identifiers, so prefix is not needed if withUid then return '*<span class="nowrap"><span class="uid">'..link..'</span></span>\n' end return '*<span class="nowrap">'..link..'</span>\n' end return '* <span class="error">The '..id..' id '..rawValues..' is not valid.</span>'..addCat(faultyCat)..'\n' end --[[==========================================================================]] --[[ Property formatting functions ]] --[[==========================================================================]] -- If a link has a suitable entry in the global inter-wiki prefix table at [[:m:Interwiki_map]], -- please consider routing through this prefix rather than as external link URL. -- This will ease future maintenance as necessary updates to the link can be centrally carried out there rather than by updating this module. -- The "external link" icon would disappear for such entries. function p.aagLink( id, label) --P3372's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[https://www.aucklandartgallery.com/explore-art-and-ideas/artist/'..id..'/ '..(label or 'Auckland')..']'..p.getCatForId( 'AAG' ) end function p.acmLink( id, label ) --P864's format regex: \d{11} (e.g. 12345678901) if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d$' ) then return false end return '[https://dl.acm.org/profile/'..id..' '..(label or 'Association for Computing Machinery')..']'..p.getCatForId( 'ACM-DL' ) end function p.adbLink( id, label ) --P1907's format regex: [a-z][-a-z]+-([1-3]\d|[1-9])\d{0,3} (e.g. barton-sir-edmund-toby-71) if not id:match( '^[a-z][-a-z]+-[1-3]%d%d?%d?%d?$' ) and not id:match( '^[a-z][-a-z]+-[1-9]%d?%d?%d?$' ) then return false end return '[http://adb.anu.edu.au/biography/'..id..' '..(label or 'Australia')..']'..p.getCatForId( 'ADB' ) end function p.admiraltyLink(id,label) --P3562's format regex: [A-Q]\d{4}(\.\d+)? (e.g. D1204.1) if not id:match('^[A-Q]%d%d%d%d$') and not id:match('^[A-Q]%d%d%d%d%.%d+$') then return false end return id..p.getCatForId( 'admiralty' ) end function p.agsaLink( id, label ) --P6804's format regex: [1-9]\d* (e.g. 3625) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://www.agsa.sa.gov.au/collection-publications/collection/creators/_/'..id..'/ '..(label or 'South Australia')..']'..p.getCatForId( 'AGSA' ) end function p.ARLHSLink(id,label) --P2980's format regex: [A-Z]{3}\d{3,4}[A-Z]?| e.g. LAT023 if not id:match('^[A-Z][A-Z][A-Z]%d%d%d%d?[A-Z]?$') then return false end return '[http://wlol.arlhs.com/lighthouse/'..id..'.html '..(label or 'ARLHS')..']'..p.getCatForId( 'ARLHS' ) end function p.autoresuyLink( id, label ) --P2558's format regex: [1-9]\d{0,4} (e.g. 12345) if not id:match( '^[1-9]%d?%d?%d?%d?$' ) then return false end return '[https://autores.uy/autor/'..id..' '..(label or 'Uruguay')..']'..p.getCatForId( 'autores.uy' ) end function p.awrLink( id, label ) --P4186's format regex: (([A-Z]{3}\d{4})|([A-Z]{2}\d{5}))[a-z] (e.g. PR00768b) if not id:match( '^[A-Z][A-Z][A-Z]%d%d%d%d[a-z]$' ) and not id:match( '^[A-Z][A-Z]%d%d%d%d%d[a-z]$' ) then return false end return '[http://www.womenaustralia.info/biogs/'..id..'.htm '..(label or 'Australian Women\'s Register')..']'..p.getCatForId( 'AWR' ) end function p.bibsysLink( id, label ) --P1015's format regex: [1-9]\d* or [1-9](\d{0,8}|\d{12}) (e.g. 1234567890123) --TODO: follow up @ [[d:Property talk:P1015#Discrepancy between the 2 regex constraints]] or escalate/investigate if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) and not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d$' ) then return false end return '[https://authority.bibsys.no/authority/rest/authorities/html/'..id..' '..(label or 'Norway')..']'..p.getCatForId( 'BIBSYS' ) end function p.bildLink( id, label ) --P2092's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[https://www.bildindex.de/document/obj'..id..' '..(label or 'Bildindex (Germany)')..']'..p.getCatForId( 'Bildindex' ) end function p.bncLink( id, label ) --P1890's format regex: \d{9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return false end return '[http://www.bncatalogo.cl/F?func=direct&local_base=red10&doc_number='..id..' '..(label or 'Chile')..']'..p.getCatForId( 'BNC' ) end function p.bneLink( id, label ) --P950's format regex: (XX|FF|a)\d{4,7}|(bima|bimo|bica|bis[eo]|bivi|Mise|Mimo|Mima)\d{10} (e.g. XX1234567) if not id:match( '^[XF][XF]%d%d%d%d%d?%d?%d?$' ) and not id:match( '^a%d%d%d%d%d?%d?%d?$' ) and not id:match( '^bi[mcsv][aoei]%d%d%d%d%d%d%d%d%d%d$' ) and not id:match( '^Mi[sm][eoa]%d%d%d%d%d%d%d%d%d%d$' ) then return false end return '[http://catalogo.bne.es/uhtbin/authoritybrowse.cgi?action=display&authority_id='..id..' '..(label or 'Spain')..']'..p.getCatForId( 'BNE' ) --no https as of 9/2019 end function p.bnfLink( id, label ) --P268's format regex: \d{8}[0-9bcdfghjkmnpqrstvwxz] (e.g. 123456789) if not id:match( '^c?b?%d%d%d%d%d%d%d%d[0-9bcdfghjkmnpqrstvwxz]$' ) then return false end --Add cb prefix if it has been removed if not id:match( '^cb.+$' ) then id = 'cb'..id end return '[https://catalogue.bnf.fr/ark:/12148/'..id..' '..(label or 'France')..'] [https://data.bnf.fr/ark:/12148/'..id..' (data)]'..p.getCatForId( 'BNF' ) end function p.bnmmLink( id, label ) --P3788's format regex: \d{9} (e.g. 000024044) if id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return '[https://catalogo.bn.gov.ar/F/?func=direct&local_base=BNA10&doc_number='..id..' '..(label or 'Argentina')..']'..p.getCatForId( 'BNMM' ) else return false end end function p.botanistLink( id, label ) --P428's format regex: ('t )?(d')?(de )?(la )?(van (der )?)?(Ma?c)?(De)?(Di)?\p{Lu}?C?['\p{Ll}]*([-'. ]*(van )?(y )?(d[ae][nr]?[- ])?(Ma?c)?[\p{Lu}bht]?C?['\p{Ll}]*)*\.? ?f?\.? (e.g. L.) --not easily/meaningfully implementable in Lua's regex since "(this)?" is not allowed... if not mw.ustring.match( id, "^[%u%l%d%. '-]+$" ) then --better than nothing return false end id = id:gsub(' +', '%%20') return '[https://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation='..id..' '..(label or 'International Plant Names Index')..']'..p.getCatForId( 'Botanist' ) end function p.bpnLink( id, label ) --P651's format regex: \d{6,8} (e.g. 00123456) if not id:match( '^%d%d%d%d%d%d%d%d$' ) and --original format regex, changed 8/2019 to not id:match( '^0?%d%d%d%d%d%d%d$' ) and --allow 1-2 leading 0s, allowed by the website not id:match( '^0?0?%d%d%d%d%d%d$' ) then return false end return '[http://www.biografischportaal.nl/en/persoon/'..id..' '..(label or 'Netherlands')..']'..p.getCatForId( 'BPN' ) --no https as of 9/2019 end function p.canticLink( id, label ) --P1273's format regex: a\d{7}[0-9x] (e.g. a10640745) if not id:match( '^a%d%d%d%d%d%d%d[%dx]$' ) then return false end return '[http://cantic.bnc.cat/registres/CUCId/'..id..' '..(label or 'Catalonia')..']'..p.getCatForId( 'CANTIC' ) --no https as of 10/2019 end function p.canticnLink( id, label ) --P9984's format regex: 981(0|1)\d{9}06706 (e.g. 981058515460906706) if not id:match( '^981[0-1]%d%d%d%d%d%d%d%d%d06706$' ) then return false end return '[https://cantic.bnc.cat/registre/'..id..' '..(label or 'Catalonia')..']'..p.getCatForId( 'CANTICN' ) end function p.ccgLink( id, label ) --P3920's format regex: ([NAIP])?[1-9]\d*(\.\d+)? (e.g. A1761) if not id:match( '^[NAIP]?[1-9]%d*$' ) and not id:match( '^[NAIP]?[1-9]%d*%.%d+$' ) then return false end return id..p.getCatForId( 'CCG' ) end function p.ciniiLink( id, label ) --P271's format regex: DA\d{7}[\dX] (e.g. DA12345678) if not id:match( '^DA%d%d%d%d%d%d%d[%dX]$' ) then return false end return '[https://ci.nii.ac.jp/author/'..id..'?l=en '..(label or 'CiNii (Japan)')..']'..p.getCatForId( 'CINII' ) end function p.cwgcLink( id, label ) --P1908's format regex: [1-9]\d* (e.g. 75228351) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://www.cwgc.org/find-war-dead/casualty/'..id..'/ '..(label or 'Commonwealth War Graves Commission')..']'..p.getCatForId( 'CWGC' ) end function p.emuLink( id, label ) --P4613's format regex: \d{1,6} (e.g. 15409 (or 015409)) if not id:match( '^%d%d?%d?%d?%d?%d?$' ) then return false end return '[http://esu.com.ua/search_articles.php?id='..id..' '..(label or 'Ukraine')..']'..p.getCatForId( 'EMU' ) end function p.daaoLink( id, label ) --P1707's format regex: [a-z\-]+\d* (e.g. rolf-harris) if not id:match( '^[a-z%-]+%d*$' ) then return false end return '[https://www.daao.org.au/bio/'..id..' '..(label or 'Australian Artists')..']'..p.getCatForId( 'DAAO' ) end function p.dblpLink( id, label ) --P2456's format regex: \d{2,3} /\d+(-\d+)?|[a-z] /[a-zA-Z][0-9A-Za-z]*(-\d+)? (e.g. 123/123) if not id:match( '^%d%d%d?/%d+$' ) and not id:match( '^%d%d%d?/%d+%-%d+$' ) and not id:match( '^[a-z]/[a-zA-Z][0-9A-Za-z]*$' ) and not id:match( '^[a-z]/[a-zA-Z][0-9A-Za-z]*%-%d+$' ) then return false end return '[https://dblp.org/pid/'..id..' '..(label or 'DBLP (computer science)')..']'..p.getCatForId( 'DBLP' ) end function p.dibLink( id, label ) --P6829's format regex: 0[01]\d{4}(\.[A-D])? (e.g. 001953) if not id:match( '^0[01]%d%d%d%d%.?[A-D]?$' ) then return false end return '[https://dib.cambridge.org/viewReadPage.do?articleId='..id..' '..(label or 'Ireland')..']'..p.getCatForId( 'DIB' ) end function p.dsiLink( id, label ) --P2349's format regex: [1-9]\d* (e.g. 1538) if not id:match( '^[1-9]%d*$' ) then return false end return '[http://www.uni-stuttgart.de/hi/gnt/dsi2/index.php?table_name=dsi&function=details&where_field=id&where_value='..id..' '..(label or 'Scientific illustrators')..']'..p.getCatForId( 'DSI' ) end function p.dtbioLink( id, label ) --P7902's format regex: 1[0-9]{7,8}[0-9X] (e.g. 118554700) if not id:match( '^1[0-9]%d%d%d%d%d%d%d?[0-9X]$' ) then return false end return '[https://www.deutsche-biographie.de/pnd'..id..'.html?language=en '..(label or 'Germany')..']'..p.getCatForId( 'DTBIO' ) end function p.fastLink( id, label ) --P2163's format regex: [1-9]\d{0,7} (e.g. 1916996) if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[http://id.worldcat.org/fast/'..id..'/ '..(label or 'Faceted Application of Subject Terminology')..']'..p.getCatForId( 'FAST' ) end function p.fnzaLink( id, label ) --P6792's format regex: [1-9]\d* (e.g. 9785) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://findnzartists.org.nz/artist/'..id..'/ '..(label or 'New Zealand Artists')..']'..p.getCatForId( 'FNZA' ) end function p.gndLink( id, label ) --P227's format regex: 1[012]?\d{7}[0-9X]|[47]\d{6}-\d|[1-9]\d{0,7}-[0-9X]|3\d{7}[0-9X] (e.g. 4079154-3) if not id:match( '^1[012]?%d%d%d%d%d%d%d[0-9X]$' ) and not id:match( '^[47]%d%d%d%d%d%d%-%d$' ) and not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%-[0-9X]$' ) and not id:match( '^3%d%d%d%d%d%d%d[0-9X]$' ) then return false end return '[https://d-nb.info/gnd/'..id..' '..(label or 'Germany')..']'..p.getCatForId( 'GND' ) end function p.googleLink( id, label ) --P1960's format regex: [-_0-9A-Za-z]{12} (e.g. CUO0vDcAAAAJ) if not id:match( '^[%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u]$' ) then return false end return '[https://scholar.google.com/citations?user='..id..' '..(label or 'Google Scholar')..']'..p.getCatForId( 'Google Scholar' ) end function p.hdsLink( id, label ) --P902's format regex: \d{6} (e.g. 050123) if not id:match( '^%d%d%d%d%d%d$' ) then return false end return '[https://hls-dhs-dss.ch/fr/articles/'..id..' '..(label or 'Historical Dictionary of Switzerland')..']'..p.getCatForId( 'HDS' ) end function p.iaafLink( id, label ) --P1146's format regex: [0-9][0-9]* (e.g. 012) if not id:match( '^%d+$' ) then return false end return '[https://www.iaaf.org/athletes/_/'..id..' '..(label or 'World Athletics')..']'..p.getCatForId( 'IAAF' ) end function p.iccuLink( id, label ) --P396's format regex: \D{2}[A-Z0-3]V\d{6} (e.g. CFIV000163) if not id:match( '^%u%u[%u0-3]V%d%d%d%d%d%d$' ) then --legacy: %u used here instead of %D (but the faulty ID cat is empty, out of ~12k uses) return false end return '[https://opac.sbn.it/nome/'..id..' '..(label or 'Italy')..']'..p.getCatForId( 'ICCU' ) end function p.iciaLink( id, label ) --P1736's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[https://www.imj.org.il/artcenter/newsite/en/?artist='..id..' '..(label or 'ICIA (Israel)')..']'..p.getCatForId( 'ICIA' ) end function p.ieuLink( id, label ) --P9070's format regex: [A-Z]\\[A-Z]\\[A-Za-z0-9]+ (e.g. K\Y\Kyiv) if not id:match( '^[A-Z]\\[A-Z]\\%w+$' ) then return false end return '[http://www.encyclopediaofukraine.com/display.asp?linkpath=pages\\'..id..' '..(label or 'Internet Encyclopedia of Ukraine')..']'..p.getCatForId( 'IEU' ) end function p.isniLink( id, label ) id = p.validateIsni( id ) --e.g. 0000-0000-6653-4145 if not id then return false end return '[https://isni.org/isni/'..id..' '..(label or 'ISNI')..']'..p.getCatForId( 'ISNI' ) end function p.j9uLink( id, label ) --P8189's format regex: 9870(0|1)\d{8}05171 (e.g. 987007305652505171) if not id:match( '^9870[0-1]%d%d%d%d%d%d%d%d05171$' ) then return false end return '[http://uli.nli.org.il/F/?func=find-b&local_base=NLX10&find_code=UID&request='..id..' '..(label or 'Israel')..']'..p.getCatForId( 'J9U' ) end function p.jocondeLink( id, label ) --P347's format regex: [\-0-9A-Za-z]{11} (e.g. 12345678901) local regex = '^'..string.rep('[%-0-9A-Za-z]', 11)..'$' if not id:match( regex ) then return false end return '[https://www.pop.culture.gouv.fr/notice/joconde/'..id..' '..(label or 'Joconde (France)')..']'..p.getCatForId( 'Joconde' ) end function p.kulturnavLink( id, label ) --P1248's format regex: [0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end return '[http://kulturnav.org/'..id..' '..(label or 'KulturNav (Norway)')..']'..p.getCatForId( 'KULTURNAV' ) --no https as of 9/2019 end function p.lccnLink( id, label ) local parts = p.splitLccn( id ) --e.g. n78039510 if not parts then return false end local lccnType = parts[1] ~= 'sh' and 'names' or 'subjects' id = parts[1] .. parts[2] .. p.append( parts[3], '0', 6 ) return '[https://id.loc.gov/authorities/'..lccnType..'/'..id..' '..(label or 'United States')..']'..p.getCatForId( 'LCCN' ) end function p.lirLink( id, label ) --P886's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[http://www.e-lir.ch/e-LIR___Lexicon.'..id..'.450.0.html '..(label or 'Lexicon Istoric Retic (Switzerland)')..']'..p.getCatForId( 'LIR' ) --no https as of 9/2019 end function p.lnbLink( id, label ) --P1368's format regex: \d{9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return false end return '[https://kopkatalogs.lv/F?func=direct&local_base=lnc10&doc_number='..id..'&P_CON_LNG=ENG '..(label or 'Latvia')..']'..p.getCatForId( 'LNB' ) end function p.marinaMilitareLink( id, label ) --P3863's format regex: [1-9]\d* (e.g. 3856) if id:match( '^[1-9]%d*$' ) then return '[http://www.marina.difesa.it/cosa-facciamo/per-la-difesa-sicurezza/fari/Pagine/'..id..'.aspx '..(label or 'Italy')..']'..p.getCatForId( 'Marina Militare' ) else return false end end function p.mathsnLink( id, label ) --P4955's format regex: [1-9]\d{4,6} (e.g. 175270) if not id:match( '^[1-9]%d%d%d%d%d?%d?$' ) then return false end return '[https://mathscinet.ams.org/mathscinet/MRAuthorID/'..id..' '..(label or 'MathSciNet')..']'..p.getCatForId( 'MATHSN' ) end function p.mbaLink( id, label ) --P434's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/artist/'..id local cat = p.getCatForId( 'MusicBrainz' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBA (identifier)|MusicBrainz]] ['..url..' artist]'..cat end end function p.mbareaLink( id, label ) --P982's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/area/'..id local cat = p.getCatForId( 'MusicBrainz area' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBAREA (identifier)|MusicBrainz]] ['..url..' area]'..cat end end function p.mbiLink( id, label ) --P1330's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/instrument/'..id local cat = p.getCatForId( 'MusicBrainz instrument' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBI (identifier)|MusicBrainz]] ['..url..' instrument]'..cat end end function p.mblLink( id, label ) --P966's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/label/'..id local cat = p.getCatForId( 'MusicBrainz label' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBL (identifier)|MusicBrainz]] ['..url..' label]'..cat end end function p.mbpLink( id, label ) --P1004's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/place/'..id local cat = p.getCatForId( 'MusicBrainz place' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBP (identifier)|MusicBrainz]] ['..url..' place]'..cat end end function p.mbrgLink( id, label ) --P436's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/release-group/'..id local cat = p.getCatForId( 'MusicBrainz release group' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBRG (identifier)|MusicBrainz]] ['..url..' release group]'..cat end end function p.mbsLink( id, label ) --P1407's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/series/'..id local cat = p.getCatForId( 'MusicBrainz series' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBS (identifier)|MusicBrainz]] ['..url..' series]'..cat end end function p.mbwLink( id, label ) --P435's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB) if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then return false end local url = 'https://musicbrainz.org/work/'..id local cat = p.getCatForId( 'MusicBrainz work' )--special cat name if label then return '['..url..' '..label..']'..cat else return '[[MBW (identifier)|MusicBrainz]] ['..url..' work]'..cat end end function p.mgpLink( id, label ) --P549's format regex: \d{1,6} (e.g. 123456) if not id:match( '^%d%d?%d?%d?%d?%d?$' ) then return false end return '[https://www.mathgenealogy.org/id.php?id='..id..' '..(label or 'Mathematics Genealogy Project')..']'..p.getCatForId( 'MGP' ) end function p.mtLink( id, label ) --P3601's format regex: \d{10} (e.g. 1000004707) if id:match( '^%d%d%d%d%d%d%d%d%d%d$' ) then return '[https://www.marinetraffic.com/en/ais/details/lights/'..id..' '..(label or 'MarineTraffic')..']'..p.getCatForId( 'MarineTraffic' ) else return false end end function p.naraLink( id, label ) --P1225's format regex: ^([1-9]\d{0,8})$ (e.g. 123456789) if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[https://catalog.archives.gov/id/'..id..' '..(label or 'National Archives (US)')..']'..p.getCatForId( 'NARA' ) end function p.nclLink( id, label ) --P1048's format regex: \d+ (e.g. 1081436) if not id:match( '^%d+$' ) then return false end return '[http://aleweb.ncl.edu.tw/F/?func=accref&acc_sequence='..id..'&CON_LNG=ENG '..(label or 'Taiwan')..']'..p.getCatForId( 'NCL' ) --no https as of 9/2019 end function p.ndlLink( id, label ) --P349's format regex: 0?\d{8} (e.g. 012345678) if not id:match( '^0?%d%d%d%d%d%d%d%d$' ) then return false end return '[https://id.ndl.go.jp/auth/ndlna/'..id..' '..(label or 'Japan')..']'..p.getCatForId( 'NDL' ) end function p.ngaLink(id,label) --P3563's format rgex: 11[0-6]-\d+(\.\d+)? (e.g. 114-7721.2) if not id:match('^11[0-6]%-%d+%.?%d*$') then return false end return '[https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fmsi.nga.mil%2FqueryResults%3Fpublications%2Fngalol%2Flights-buoys%3Fvolume%3D%251%26featureNumber%3D%252%26includeRemovals%3Dfalse%26output%3Dhtml&exp=(%5Cd%7B3%7D)-(.*)&id='..id..' '..(label or 'NGA')..']'..p.getCatForId( 'NGA' ) end function p.ngvLink( id, label ) --P2041's format regex: \d+ (e.g. 12354) if not id:match( '^%d+$' ) then return false end return '[https://www.ngv.vic.gov.au/explore/collection/artist/'..id..'/ '..(label or 'Victoria')..']'..p.getCatForId( 'NGV' ) end function p.nkcLink( id, label ) --P691's format regex: [a-z]{2,4}[0-9]{2,14} (e.g. abcd12345678901234) if not id:match( '^[a-z][a-z][a-z]?[a-z]?%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[https://aleph.nkp.cz/F/?func=find-c&local_base=aut&ccl_term=ica='..id..'&CON_LNG=ENG '..(label or 'Czech Republic')..']'..p.getCatForId( 'NKC' ) end function p.nlaLink( id, label ) --P409's format regex: [1-9][0-9]{0,11} (e.g. 123456789012) if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[https://nla.gov.au/anbd.aut-an'..id..' '..(label or 'Australia')..']'..p.getCatForId( 'NLA' ) end function p.nlgLink( id, label ) --P3348's format regex: [1-9]\d* (e.g. 1) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://data.nlg.gr/resource/authority/record'..id..' '..(label or 'Greece')..']'..p.getCatForId( 'NLG' ) end function p.nlkLink( id, label ) --P5034's format regex: (KAB|KAC|KSH)([0-9]{4}|[0-9]{4}[a-zA-Z])[0-9]{4,6} (e.g. KAC201501465) if not id:match( '^KAB%d%d%d%d%a?%d%d%d%d%d?%d?$' ) and not id:match( '^KAC%d%d%d%d%a?%d%d%d%d%d?%d?$' ) and not id:match( '^KSH%d%d%d%d%a?%d%d%d%d%d?%d?$' ) then return false end return '[https://lod.nl.go.kr/resource/'..id..' '..(label or 'Korea')..']'..p.getCatForId( 'NLK' ) end function p.nlpLink( id, label ) --P1695's format regex: 9810[0-9]\d* or A[0-9]{7}[0-9X] (e.g. 9810123456789012345 or A10414836) if not id:match( '^9810%d+$' ) and not id:match( '^A%d%d%d%d%d%d%d[%dX]$' ) then return false end return '[https://tools.wmflabs.org/wikidata-externalid-url?p=1695&id='..id..' '..(label or 'Poland')..']'..p.getCatForId( 'NLP' ) end function p.nlrLink( id, label ) --P1003's format regex: \d{9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return false end return '[http://aleph.bibnat.ro:8991/F/?func=direct&local_base=NLR10&doc_number='..id..' '..(label or 'Romania')..']'..p.getCatForId( 'NLR' ) end function p.nskLink( id, label ) --P1375's format regex: \d{9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then return false end return '[http://katalog.nsk.hr/F/?func=direct&doc_number='..id..'&local_base=nsk10 '..(label or 'Croatia')..']'..p.getCatForId( 'NSK' ) --no https as of 9/2019 end function p.ntaLink( id, label ) --P1006's format regex: \d{8}[\dX] (e.g. 12345678X) if not id:match( '^%d%d%d%d%d%d%d%d[%dX]$' ) then return false end return '[http://data.bibliotheken.nl/id/thes/p'..id..' '..(label or 'Netherlands')..']'..p.getCatForId( 'NTA' ) end function p.orcidLink( id, label ) id = p.validateIsni( id ) --e.g. 0000-0002-7398-5483 if not id then return false end id = id:sub( 1, 4 )..'-'..id:sub( 5, 8 )..'-'..id:sub( 9, 12 )..'-'..id:sub( 13, 16 ) return '[https://orcid.org/'..id..' '..(label or 'ORCID')..']'..p.getCatForId( 'ORCID' ) end function p.picLink( id, label ) --P2750's format regex: [1-9]\d* (e.g. 1) if not id:match( '^[1-9]%d*$' ) then return false end return '[https://pic.nypl.org/constituents/'..id..' '..(label or 'Photographers\' Identities')..']'..p.getCatForId( 'PIC' ) end function p.plwabnLink( id, label ) --P7293's format regex: 981[0-9]{8}05606 (e.g. 9810696457305606) if not id:match( '^981%d%d%d%d%d%d%d%d05606*$' ) then return false end return '[http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=1&NU=1&IM=4&WI='..id..' '..(label or 'Poland')..']'..p.getCatForId( 'PLWABN' ) end function p.publonsLink( id, label ) --P3829's format regex: \d+ (e.g. 654601) if not id:match( '^%d+$' ) then return false end return '[https://publons.com/author/'..id..'/ '..(label or 'Publons (researchers)')..']'..p.getCatForId( 'Publons' ) end function p.ridLink( id, label ) --P1053's format regex: [A-Z]{1,3}-\d{4}-(19|20)\d\d (e.g. AAS-5150-2020) if not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-19%d%d$' ) and not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-20%d%d$' ) then return false end return '[https://www.researcherid.com/rid/'..id..' '..(label or 'ResearcherID')..']'..p.getCatForId( 'RID' ) end function p.rismLink( id, label ) --P5504's format regex: (pe|ks)?\[1-9]d* (e.g. pe30006410) if not id:match( '^pe[1-9]%d*$' ) and --99% start with 'pe' not id:match( '^ks[1-9]%d*$' ) and not id:match( '^[1-9]%d*$' ) then return false end return '[https://opac.rism.info/search?id='..id..' '..(label or 'RISM (France)')..']'..p.getCatForId( 'RISM' ) end function p.reroLink( id, label ) --P3065's format regex: 0[1-2]-[A-Z0-9]{1,10} (e.g. 02-A012345678) if not id:match( '^0[1-2]%-[A-Z%d][A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?$' ) then return false end return '[http://data.rero.ch/'..id..' '..(label or 'RERO (Switzerland)')..']'..p.getCatForId( 'RERO' ) end function p.rkdartistsLink( id, label ) --P650's format regex: [1-9]\d{0,5} (e.g. 123456) if not id:match( '^[1-9]%d?%d?%d?%d?%d?$' ) then return false end return '[https://rkd.nl/en/explore/artists/'..id..' '..(label or 'RKD Artists (Netherlands)')..']'..p.getCatForId( 'RKDartists' ) end function p.rkdidLink( id, label ) --P350's format regex: [1-9]\d{0,5} (e.g. 123456) if not id:match( '^[1-9]%d?%d?%d?%d?%d?$' ) then return false end return '[https://rkd.nl/nl/explore/images/'..id..' '..(label or 'RKD ID (Netherlands)')..']'..p.getCatForId( 'RKDID' ) end function p.rslLink( id, label ) --P947's format regex: \d{1,9} (e.g. 123456789) if not id:match( '^%d%d?%d?%d?%d?%d?%d?%d?%d?$' ) then return false end return '[http://aleph.rsl.ru/F?func=find-b&find_code=SYS&adjacent=Y&local_base=RSL11&request='..id..'&CON_LNG=ENG '..(label or 'Russia')..']'..p.getCatForId( 'RSL' ) --no https as of 9/2019 end function p.scopusLink( id, label ) --P1153's format regex: [1-9]\d{9,10} (e.g. 35247902700) if not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d?$' ) then return false end return '[https://www.scopus.com/authid/detail.uri?authorId='..id..' '..(label or 'Scopus author')..']'..p.getCatForId( 'Scopus' ) end function p.selibrLink( id, label ) --P906's format regex: [1-9]\d{4,5} (e.g. 123456) if not id:match( '^[1-9]%d%d%d%d%d?$' ) then return false end return '[https://libris.kb.se/auth/'..id..' '..(label or 'Sweden')..']'..p.getCatForId( 'SELIBR' ) end function p.sikartLink( id, label ) --P781's format regex: \d{7,9} (e.g. 123456789) if not id:match( '^%d%d%d%d%d%d%d%d?%d?$' ) then return false end return '[http://www.sikart.ch/KuenstlerInnen.aspx?id='..id..'&lng=en '..(label or 'SIKART (Switzerland)')..']'..p.getCatForId( 'SIKART' ) --no https as of 9/2019 end function p.snacLink( id, label ) --P3430's format regex: \d*[A-Za-z][0-9A-Za-z]* (e.g. A) if not id:match( '^%d*[A-Za-z][0-9A-Za-z]*$' ) then return false end return '[https://snaccooperative.org/ark:/99166/'..id..' '..(label or 'Social Networks and Archival Context')..']'..p.getCatForId( 'SNAC-ID' ) end function p.sudocLink( id, label ) --P269's format regex: (\d{8}[\dX]|) (e.g. 026927608) if not id:match( '^%d%d%d%d%d%d%d%d[%dxX]$' ) then --legacy: allow lowercase 'x' return false end return '[https://www.idref.fr/'..id..' '..(label or 'SUDOC (France)')..']'..p.getCatForId( 'SUDOC' ) end function p.ta98Link( id, label ) --P1323's format regex: A\d{2}\.\d\.\d{2}\.\d{3}[FM]? (e.g. A12.3.45.678) if not id:match( '^A%d%d%.%d%.%d%d%.%d%d%d[FM]?$' ) then return false end local longurl = '[http://tools.wmflabs.org/wikidata-externalid-url/?p=1323&url_prefix=https:%2F%2Fwww.unifr.ch%2Fifaa%2FPublic%2FEntryPage%2FTA98%20Tree%2FEntity%20TA98%20EN%2F&url_suffix=%20Entity%20TA98%20EN.htm&id=' return longurl..id..' '..(label or 'Terminologia Anatomica')..']'..p.getCatForId( 'TA98' ) end function p.tdviaLink( id, label ) --P7314's format regex: [0-9a-z/-]+] (e.g. barkan-omer-lutfi) if not id:match( '^[%d%l/-]+$' ) then return false end return '[https://islamansiklopedisi.org.tr/'..id..' '..(label or 'İslâm Ansiklopedisi')..']'..p.getCatForId( 'TDVİA' ) end function p.tepapaLink( id, label ) --P3544's format regex: \d+ (e.g. 1) if not id:match( '^%d+$' ) then return false end return '[https://collections.tepapa.govt.nz/agent/'..id..' '..(label or 'Te Papa (New Zealand)')..']'..p.getCatForId( 'TePapa' ) end function p.tlsLink( id, label ) id = id:gsub(' +', '_') --P1362's format regex: \p{Lu}[\p{L}\d_',\.\-\(\)\*\/–&]{3,89} (e.g. Abcd) --Mediawiki page title partial URL so consider validation with mw.title or "[^#<>%[%] {|}]" local class = "[%w_',%.%-%(%)%*%/–&]" local idlen = mw.ustring.len (id) if idlen < 4 or idlen > 90 then return false end local regex = '^%u'..string.rep(class, idlen - 1)..'$' if not mw.ustring.match( id, regex ) then return false end return '[http://tls.theaterwissenschaft.ch/wiki/'..id..' '..(label or 'Theaterlexikon (Switzerland)')..']'..p.getCatForId( 'TLS' ) --no https as of 9/2019 end function p.troveLink( id, label ) --P1315's format regex: [1-9]\d{5,7} (e.g. 12345678) if not id:match( '^[1-9]%d%d%d%d%d%d?%d?$' ) then return false end return '[https://trove.nla.gov.au/people/'..id..' '..(label or 'Trove (Australia)')..']'..p.getCatForId( 'Trove' ) end function p.ukparlLink( id, label ) --P6213's format regex: [a-zA-Z\d]{8} (e.g. AQUupyiR) if not id:match( '^[a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d]$' ) then return false end return '[https://id.parliament.uk/'..id..' '..(label or 'UK Parliament')..']'..p.getCatForId( 'UKPARL' ) end function p.ulanLink( id, label ) --P245's format regex: 500\d{6} (e.g. 500123456) if not id:match( '^500%d%d%d%d%d%d$' ) then return false end return '[https://www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid='..id..' '..(label or 'Artist Names (Getty)')..']'..p.getCatForId( 'ULAN' ) end function p.uscgLink( id, label ) --P3723's format regex: [1-7]-\d{1,5}(.[1-9])? (e.g. 6-0695) if not id:match( '^[1-7]%-%d%d?%d?%d?%d?$' ) and not id:match( '^[1-7]%-%d%d?%d?%d?%d?%.%d*[1-9]$' ) then return false end return '[[USCG (identifier)|USCG]] ([https://www.navcen.uscg.gov/pdf/lightlists/LightList%20V'..mw.ustring.sub(id,1,1)..'.pdf '..id..'])'..p.getCatForId( 'USCG' ) end function p.uscongressLink( id, label ) --P1157's format regex: [A-Z]00[01]\d{3} (e.g. A000123) if not id:match( '^[A-Z]00[01]%d%d%d$' ) then return false end return '[http://bioguide.congress.gov/scripts/biodisplay.pl?index='..id..' '..(label or 'US Congress')..']'..p.getCatForId( 'USCongress' ) --no https as of 9/2019 end function p.vcbaLink( id, label ) --P8034's format regex: \d{3}\/[1-9]\d{0,5} (e.g. 494/9793) if not id:match( '^%d%d%d\/[1-9]%d?%d?%d?%d?%d?$' ) then return false end id = id:gsub('\/', '_') return '[https://opac.vatlib.it/auth/detail/'..id..' '..(label or 'Vatican')..']'..p.getCatForId( 'VcBA' ) end function p.viafLink( id, label ) --P214's format regex: [1-9]\d(\d{0,7}|\d{17,20}) (e.g. 123456789, 1234567890123456789012) if not id:match( '^[1-9]%d%d?%d?%d?%d?%d?%d?%d?$' ) and not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d?%d?%d?$' ) then return false end -- If the "VIAF" entry at [[:m:Interwiki map]] would resolve to "https://viaf.org/viaf/$1" (rather than "http://viaf.org/viaf/$1", as it currently still does), -- then the code below could change from '[https://viaf.org/viaf/'..id..' '..id..']' to '[[:VIAF:'..id..'|'..id..']]'. return '[https://viaf.org/viaf/'..id..' '..(label or 'VIAF')..']'..p.getCatForId( 'VIAF' ) end function p.worldcatidLink( id, label ) --P7859's format regex: viaf-\d+|lccn-n[a-z]?[0-9\-]+|n[cps]-.+ (e.g. viaf-100181709, lccn-n78-95332, np-verbeck,%20william$1861) if not id:match( '^viaf%-%d+$' ) and not id:match( '^lccn%-n[a-z]?[0-9%-]+$' ) and not id:match( '^n[cps]%-.+$' ) then return false end return '[https://www.worldcat.org/identities/'..mw.uri.encode(id, 'PATH')..'/ '..(label or 'WorldCat')..']'..p.getCatForId( 'WORLDCATID' ) end function p.zbmathLink( id, label ) --P1556's format regex: [a-z][a-z\-]*(\.[a-z][a-z\-]*)?(\.[0-9]*)? (e.g. turing.alan-m) local ps = {'%l[%l%-]*', '%.%l[%l%-]*', '%.%d*'} if not id:match( '^'..ps[1]..'$' ) and -- prefix with no capture options not id:match( '^'..ps[1]..ps[2]..'$' ) and -- prefix with first capture option not id:match( '^'..ps[1]..ps[3]..'$' ) and -- prefix with second capture option not id:match( '^'..ps[1]..ps[2]..ps[3]..'$' ) then -- prefix and both capture options return false end return '[https://zbmath.org/authors/?q=ai:'..id..' '..(label or 'zbMATH')..']'..p.getCatForId( 'ZBMATH' ) end --[[=========================== Helper functions =============================]] function p.append(str, c, length) while str:len() < length do str = c..str end return str end --Returns the ISNI check digit isni must be a string where the 15 first elements are digits, e.g. 0000000066534145 function p.getIsniCheckDigit( isni ) local total = 0 for i = 1, 15 do local digit = isni:byte( i ) - 48 --Get integer value total = (total + digit) * 2 end local remainder = total % 11 local result = (12 - remainder) % 11 if result == 10 then return 'X' end return tostring( result ) end --Validate ISNI (and ORCID) and retuns it as a 16 characters string or returns false if it's invalid --See http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier function p.validateIsni( id ) --P213 (ISNI) format regex: [0-9]{4} [0-9]{4} [0-9]{4} [0-9]{3}[0-9X] (e.g. 0000-0000-6653-4145) --P496 (ORCID) format regex: 0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d{3}-\d{3}[\dX] (e.g. 0000-0002-7398-5483) id = id:gsub( '[ %-]', '' ):upper() if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d[%dX]$' ) then return false end if p.getIsniCheckDigit( id ) ~= string.char( id:byte( 16 ) ) then return false end return id end function p.splitLccn( id ) --P244's format regex: (n|nb|nr|no|ns|sh)([4-9][0-9]|00|20[0-1][0-9])[0-9]{6} (e.g. n78039510) if id:match( '^%l%l?%l?%d%d%d%d%d%d%d%d%d?%d?$' ) then id = id:gsub( '^(%l+)(%d+)(%d%d%d%d%d%d)$', '%1/%2/%3' ) end if id:match( '^%l%l?%l?/%d%d%d?%d?/%d+$' ) then return mw.text.split( id, '/' ) end return false end --[[==========================================================================]] --[[ Wikidata & documentation functions ]] --[[==========================================================================]] function p.getIdsFromWikidata( itemId, property ) local ids = {} if not mw.wikibase then return ids end local statements = mw.wikibase.getBestStatements( itemId, property ) if statements then for _, statement in ipairs( statements ) do if statement.mainsnak.datavalue then table.insert( ids, statement.mainsnak.datavalue.value ) end end end return ids end function p.checkcat( category,label ) local ret='[[:Category:'..category..'|'..label..']]' if mw.title.new(category, 14).exists == false then ret = ret..' <span class="plainlinks" style="font-size:85%;">&#91;['..tostring(mw.uri.fullUrl('Category:'..category,'action=edit&preload=Template:Authority_control/preload'))..' create]&#93;</span>' end return ret end -- Creates a human-readable standalone wikitable version of p.conf, and tracking categories with page counts, for use in the documentation function p.docConfTable( frame ) local wikiTable = '<table class="wikitable sortable">'.. '<tr><th rowspan=2>Parameter</th>'.. '<th rowspan=2>Section</th>'.. '<th rowspan=2>Appears as</th>'.. '<th rowspan=2 data-sort-type=number>Wikidata property</th>'.. '<th colspan=2>Tracking categories and page counts</th></tr>'.. '<tr><th>[[:Category:Articles with authority control information|Articles]]</th>'.. '<th>[[:Category:Articles with faulty authority control information|Faulty IDs]]</th></tr>' local lang = mw.getContentLanguage() local a, f, P = 0, 0, 0 --cumulative sums for _, conf in pairs( p.conf ) do local param, pid, section = conf[1], conf[2], conf[4] local appearsAs if conf.prefix then appearsAs = conf.prefix else appearsAs = conf[3](conf[5]) end local link = conf.link or param..' (identifier)' local category = conf.category or param local args = { id = 'f', pid } local wpl = frame:expandTemplate{ title = 'Wikidata property link', args = args } --cats local articleCat = 'Articles with '..category..' identifiers' local faultyCat = 'Articles with faulty '..category..' identifiers' --counts local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') ) local faultyCount = lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, 'pages') ) --calcs P = P + 1 --property count a = a + lang:parseFormattedNumber(articleCount) f = f + lang:parseFormattedNumber(faultyCount) --concat wikiTable = wikiTable..'<tr><td>[['..link..'|'..param..']]</td>'.. '<td>'..section..'</td>'.. '<td>'..appearsAs..'</td>'.. '<td data-sort-value='..pid..'>'..wpl..'</td>'.. '<td style="text-align: right;">'..p.checkcat(articleCat,articleCount)..'</td>'.. '<td style="text-align: right;">'..p.checkcat(faultyCat,faultyCount)..'</td></tr>' end --append derivative WorldCat cats local wcd = { 'WorldCat-LCCN', 'WorldCat-VIAF' } for _, w in pairs(wcd) do local articleCat = 'Articles with '..w..' identifiers' local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') ) local appearsAs if w == 'WorldCat-LCCN' then appearsAs = '[https://www.worldcat.org/identities/lccn-n79-113947 WorldCat (via Library of Congress)]' else appearsAs = '[https://www.worldcat.org/identities/containsVIAFID/12345789 WorldCat (via VIAF)]' end a = a + lang:parseFormattedNumber(articleCount) wikiTable = wikiTable..'<tr><td>-</td>'.. '<td>General</td>'.. '<td>'..appearsAs..'</td>'.. '<td data-sort-value='..w..'>—</td>'.. '<td style="text-align: right;">[[:Category:'..articleCat..'|'..articleCount..']]</td>'.. '<td style="text-align: right;">—</td></tr>' end --append sums wikiTable = wikiTable..'<tr><th style="text-align: right;" colspan=3>Totals</th>'.. '<th style="text-align: right;">'..lang:formatNum(P)..'</th>'.. '<th style="text-align: right;">'..lang:formatNum(a)..'</th>'.. '<th style="text-align: right;">'..lang:formatNum(f)..'</th></tr></table>' return require('Module:Suppress categories').main(wikiTable) end --[[==========================================================================]] --[[ Configuration ]] --[[==========================================================================]] -- Please use "<parameter> (identifier)" redirects rather than linking directly to the target page. -- This reduces clutter in "What links here" on both the redirect and the target, -- and improves reverse lookup of articles where a manifestation of each identifier is used. -- p.conf table basic format: { 'parameter name', propertyId # in Wikidata, formatting/validation function, section, example ID for documentation } -- p.conf table optional named parameters: -- link: to override the link in the documentation (defaults to "<parameter> (identifer)") -- category: to override the ID in category names (defaults to "... with <parameter> identifiers") -- prefix: to include a prefix (usually a wikilink explaining what the identifier is) before the external link itself p.conf = { { 'AAG', 3372, p.aagLink, 'Art galleries and museums', '1' }, { 'ACM-DL', 864, p.acmLink, 'Scientific databases', '12345678901', link = 'ACM DL (identifier)' }, { 'ADB', 1907, p.adbLink,'Biographical dictionaries', 'barton-sir-edmund-toby-71' }, { 'admiralty', 3562, p.admiraltyLink, 'Lighthouse identifiers', 'D1204.1', prefix='[[Admiralty number|Admiralty]]'}, { 'AGSA', 6804, p.agsaLink, 'Art galleries and museums', '3625' }, { 'ARLHS', 2980, p.ARLHSLink, 'Lighthouse identifiers', 'LAT023'}, { 'autores.uy', 2558, p.autoresuyLink, 'Biographical dictionaries', '12345' }, { 'AWR', 4186, p.awrLink, 'Biographical dictionaries', 'PR00768b' }, { 'BIBSYS', 1015, p.bibsysLink, 'National libraries', '1234567890123' }, { 'Bildindex', 2092, p.bildLink, 'Art research institutes', '1' }, { 'BNC', 1890, p.bncLink, 'National libraries', '123456789' }, { 'BNE', 950, p.bneLink, 'National libraries', 'XX1234567' }, { 'BNF', 268, p.bnfLink, 'National libraries', '123456789' }, { 'BNMM', 3788, p.bnmmLink, 'National libraries', '000024044' }, { 'Botanist', 428, p.botanistLink , 'Scientific databases', 'L.' }, { 'BPN', 651, p.bpnLink , 'Biographical dictionaries', '12345678' }, { 'CANTIC', 1273, p.canticLink, 'National libraries', 'a12345678' }, { 'CANTICN', 9984, p.canticnLink, 'National libraries', '981058515460906706' }, { 'CCG', 3920, p.ccgLink, 'Lighthouse identifiers', 'A1761', prefix='[[CCG (identifier)|CCG]]' }, { 'CINII', 271, p.ciniiLink, 'Scientific databases', 'DA12345678', link = 'CiNii (identifier)' }, { 'CWGC', 1908, p.cwgcLink, 'Other', '1234567' }, { 'DAAO', 1707, p.daaoLink, 'Art research institutes', 'rolf-harris' }, { 'DBLP', 2456, p.dblpLink, 'Scientific databases', '123/123' }, { 'DIB', 6829, p.dibLink, 'Biographical dictionaries', '001953' }, { 'DSI', 2349, p.dsiLink, 'Art research institutes', '1538' }, { 'DTBIO', 7902, p.dtbioLink, 'Biographical dictionaries', '118554700' }, { 'EMU', 4613, p.emuLink, 'National libraries', '15409' }, { 'FAST', 2163, p.fastLink, 'Other', '1' }, { 'FNZA', 6792, p.fnzaLink, 'Art research institutes', '12' }, { 'GND', 227, p.gndLink, 'National libraries', '4079154-3' }, { 'Google Scholar', 1960, p.googleLink, 'Scientific databases', 'QPdLuj8AAAAJ' }, { 'HDS', 902, p.hdsLink, 'Other', '050123' }, { 'IAAF', 1146, p.iaafLink, 'Other', '123' }, { 'ICCU', 396, p.iccuLink, 'National libraries', 'CFIV000163' }, --formerly SBN { 'ICIA', 1736, p.iciaLink, 'Art research institutes', '1' }, { 'IEU', 9070, p.ieuLink, 'Other', 'N\\A\\NationalAcademyofArtandArchitecture' }, { 'ISNI', 213, p.isniLink, 'General', '0000-0000-6653-4145', prefix = '[[ISNI (identifier)|ISNI]]' }, { 'J9U', 8189, p.j9uLink, 'National libraries', '987007305652505171' }, { 'Joconde', 347, p.jocondeLink, 'Art research institutes', '12345678901' }, { 'KULTURNAV', 1248, p.kulturnavLink, 'Art research institutes', '12345678-1234-1234-1234-1234567890AB', link = 'KulturNav (identifier)' }, { 'LCCN', 244, p.lccnLink, 'National libraries', 'n78039510' }, { 'LIR', 886, p.lirLink, 'Other', '1' }, { 'LNB', 1368, p.lnbLink, 'National libraries', '123456789' }, { 'Marina Militare', 3863, p.marinaMilitareLink, 'Lighthouse identifiers', '3856' }, { 'MarineTraffic', 3601, p.mtLink, 'Lighthouse identifiers', '1000004707' }, { 'MATHSN', 4955, p.mathsnLink, 'Scientific databases', '175270' }, { 'MBA', 434, p.mbaLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz' }, --special cat name { 'MBAREA', 982, p.mbareaLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz area' }, --special cat name { 'MBI', 1330, p.mbiLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz instrument' }, --special cat name { 'MBL', 966, p.mblLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz label' }, --special cat name { 'MBP', 1004, p.mbpLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz place' }, --special cat name { 'MBRG', 436, p.mbrgLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz release group' }, --special cat name { 'MBS', 1407, p.mbsLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz series' }, --special cat name { 'MBW', 435, p.mbwLink, 'Other', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz work' }, --special cat name { 'MGP', 549, p.mgpLink, 'Scientific databases', '123456' }, { 'NARA', 1225, p.naraLink, 'Other', '12345678' }, { 'NCL', 1048, p.nclLink, 'National libraries', '1081436' }, { 'NDL', 349, p.ndlLink, 'National libraries', '012345678' }, { 'NGA', 3563, p.ngaLink, 'Lighthouse identifiers', '114-5592'}, { 'NGV', 2041, p.ngvLink, 'Art galleries and museums', '12354' }, { 'NKC', 691, p.nkcLink, 'National libraries', 'abcd12345678901234' }, { 'NLA', 409, p.nlaLink, 'National libraries', '123456789012' }, { 'NLG', 3348, p.nlgLink, 'National libraries', '12345678' }, { 'NLK', 5034, p.nlkLink, 'National libraries', 'KAB197000000' }, { 'NLP', 1695, p.nlpLink, 'National libraries', '9810123456789012345' }, { 'NLR', 1003, p.nlrLink, 'National libraries', '123456789' }, { 'NSK', 1375, p.nskLink, 'National libraries', '123456789' }, { 'NTA', 1006, p.ntaLink, 'National libraries', '12345678X' }, { 'ORCID', 496, p.orcidLink, 'General', '0000-0002-7398-5483', prefix = '[[ORCID (identifier)|ORCID]]' }, { 'PIC', 2750, p.picLink, 'Art research institutes', '1' }, { 'PLWABN', 7293, p.plwabnLink, 'National libraries', '9812345678905606' }, { 'Publons', 3829, p.publonsLink, 'Scientific databases', '2776255' }, { 'RID', 1053, p.ridLink, 'Scientific databases', 'A-1234-1934' }, { 'RISM', 5504, p.rismLink, 'Other', 'pe1', prefix = '[[RISM (identifier)|RISM (France)]]' }, { 'RERO', 3065, p.reroLink, 'Other', '02-A012345678', prefix = '[[RERO (identifier)|RERO (Switzerland)]]' }, { 'RKDartists', 650, p.rkdartistsLink, 'Art research institutes', '123456' }, { 'RKDID', 350, p.rkdidLink, 'Art research institutes', '123456' }, { 'RSL', 947, p.rslLink, 'National libraries', '123456789' }, { 'Scopus', 1153, p.scopusLink, 'Scientific databases', '7005487412' }, { 'SELIBR', 906, p.selibrLink, 'National libraries', '123456' }, { 'SIKART', 781, p.sikartLink, 'Art research institutes', '123456789' }, { 'SNAC-ID', 3430, p.snacLink, 'Other', 'A' }, { 'SUDOC', 269, p.sudocLink, 'Other', '026927608', prefix = '[[SUDOC (identifier)|SUDOC (France)]]' }, { 'TA98', 1323, p.ta98Link, 'Scientific databases', 'A12.3.45.678' }, { 'TDVİA', 7314, p.tdviaLink, 'Other', 'asim-b-behdele' }, { 'TePapa', 3544, p.tepapaLink, 'Art galleries and museums', '1' }, { 'TLS', 1362, p.tlsLink, 'Other', 'Abcd' }, { 'Trove', 1315, p.troveLink, 'Other', '12345678', prefix = '[[Trove (identifier)|Trove (Australia)]]' }, --formerly NLA-person { 'UKPARL', 6213, p.ukparlLink, 'Other', 'AQUupyiR' }, { 'ULAN', 245, p.ulanLink, 'Art research institutes', '500123456' }, { 'USCG', 3723, p.uscgLink, 'Lighthouse identifiers', '6-0695'}, { 'USCongress', 1157, p.uscongressLink, 'Other', 'A000123', link = 'US Congress (identifier)' }, { 'VcBA', 8034, p.vcbaLink, 'National libraries', '494/9793' }, { 'VIAF', 214, p.viafLink, 'General', '123456789', prefix = '[[VIAF (identifier)|VIAF]]' }, { 'WORLDCATID', 7859, p.worldcatidLink, 'General', 'lccn-n78-95332', link = 'WorldCat Identities (identifier)' }, { 'ZBMATH', 1556, p.zbmathLink, 'Scientific databases', 'turing.alan-m' }, } -- Legitimate aliases to p.conf, for convenience -- Format: { 'alias', 'parameter name in p.conf' } p.aliases = { { 'DNB', 'GND' }, --Deutsche Nationalbibliothek -> Gemeinsame Normdatei { 'MusicBrainz', 'MBA' }, { 'MusicBrainz artist', 'MBA' }, { 'MusicBrainz label', 'MBL' }, { 'MusicBrainz release group', 'MBRG' }, { 'MusicBrainz work', 'MBW' }, { 'SBN', 'ICCU' }, --SBN alias to be deprecated at a later stage { 'TDVIA', 'TDVİA' }, --alias name without diacritics { 'tdvia', 'TDVİA' }, --lowercase variant without diacritics } -- Deprecated aliases to p.conf; tracked in [[Category:Articles with deprecated authority control identifiers]] -- Format: { 'deprecated parameter name', 'replacement parameter name in p.conf' } p.deprecated = { { 'GKD', 'GND' }, { 'PND', 'GND' }, { 'RLS', 'RSL' }, { 'SWD', 'GND' }, { 'NARA-organization', 'NARA' }, { 'NARA-person', 'NARA' }, } --[[==========================================================================]] --[[ Main ]] --[[==========================================================================]] function p.authorityControl( frame ) local resolveEntity = require( 'Module:ResolveEntityId' ) local parentArgs = frame:getParent().args --WD IDs added here later local iParentArgs = 0 --count original/manual parent args only later local worldcatCat = '' local elementsCat = '' local multipleIdCat = '' local suppressedIdCat = '' local suppressedIdCatArts = '' local deprecatedIdCat = '' local differentOnWDCat = '' local sameOnWDCat = '' local stateCat = '' --redirect aliases to proper parameter names for _, a in pairs( p.aliases ) do local alias, param = a[1], a[2] if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[alias] then parentArgs[param] = parentArgs[alias] end end --redirect deprecated parameters to proper parameter names, and assign tracking cat for _, d in pairs( p.deprecated ) do local dep, param = d[1], d[2] if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[dep] then parentArgs[param] = parentArgs[dep] if namespace == 0 then deprecatedIdCat = '[[Category:Articles with deprecated authority control identifiers|'..dep..']]' end end end --use QID= parameter for testing/example purposes only local itemId = nil if namespace ~= 0 then local qid = parentArgs['qid'] or parentArgs['QID'] if qid then itemId = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '') itemId = resolveEntity._id(itemId) --nil if unresolvable end elseif mw.wikibase then itemId = mw.wikibase.getEntityIdForCurrentPage() end --Wikidata fallback if available if itemId then local suppressedIdCount = 0 local iMatches = 0 for _, params in ipairs( p.conf ) do if params[2] > 0 then local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]] if val == nil or val == '' then local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] ) if wikidataIds[1] then if val == '' and (namespace == 0 or testcases) then suppressedIdCount = suppressedIdCount + 1 suppressedIdCat = '[[Category:Articles with suppressed authority control identifiers|'..params[1]..']]' else parentArgs[params[1]] = wikidataIds[1] --add ID from WD end end else iParentArgs = iParentArgs + 1 local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] ) if wikidataIds[1] and differentOnWDCat == '' then local bMatch = false for _, wd in pairs( wikidataIds ) do if val == wd then iMatches = iMatches + 1 bMatch = true end end if bMatch == false then differentOnWDCat = '[[Category:Pages using authority control with parameters different on Wikidata|'..params[1]..']]' end end end end end if iMatches > 0 and iMatches == iParentArgs then sameOnWDCat = '[[Category:Pages using authority control with parameters all matching Wikidata]]' end if parentArgs['arts'] == 'arts' and suppressedIdCount > 0 then if namespace == 0 or testcases then local s = 's' if suppressedIdCount == 1 then s = '' end local sCat = 'ACArt with '..suppressedIdCount..' suppressed element'..s suppressedIdCatArts = addCat(sCat) end end end --configure rows local rct = 0 local sectionOrder = { 'General', 'National libraries', 'Art galleries and museums', 'Art research institutes', 'Biographical dictionaries', 'Scientific databases', 'Lighthouse identifiers', 'Other' } local sections = { ['General'] = {}, ['National libraries'] = {}, ['Art galleries and museums'] = {}, ['Art research institutes'] = {}, ['Biographical dictionaries'] = {}, ['Scientific databases'] = {}, ['Lighthouse identifiers'] = {}, ['Other'] = {} } --don't show CANTIC if CANTICN is present, since they both go to the Library of Catalonia --and the library has deprecated CANTIC IDs in favor of CANTICN IDs if parentArgs.CANTICN or parentArgs.canticn then parentArgs.CANTIC = '' parentArgs.cantic = '' end --don't show NLP if PLWABN is present, since they both go to the National Library of Poland --and the library has deprecated NLP IDs in favor of PLWABN IDs if parentArgs.PLWABN or parentArgs.plwabn then parentArgs.NLP = '' parentArgs.nlp = '' end for _, params in ipairs( p.conf ) do local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]] local tval, tlinks = {}, {} --init tables if val and val ~= '' and type(params[3]) == 'function' then table.insert( tval, val ) if params.prefix then table.insert( tlinks, params[3]( val, '1' ) ) else table.insert( tlinks, params[3]( val ) ) end end --collect other unique vals (IDs) from WD, if present if itemId and tval[1] then local nextIdVal = 2 local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] ) for _, v in pairs( wikidataIds ) do local bnew = true for _, w in pairs( tval ) do if v == w then bnew = false end end if bnew then table.insert( tval, v ) table.insert( tlinks, params[3]( v, tostring(nextIdVal) ) ) nextIdVal = nextIdVal + 1 end end end --assemble if tval[1] then table.insert( sections[params[4]], p.createRow( params[1], tval, nil, tlinks, true, params.category, params.prefix) ) rct = rct + 1 if tval[2] then multipleIdCat = p.getCatForId( 'multiple' ) end end end --WorldCat-VIAF & WorldCat-LCCN local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID'] if worldcatId == nil then --if WORLDCATID absent but unsuppressed local viafId = parentArgs['viaf'] or parentArgs['VIAF'] local lccnId = parentArgs['lccn'] or parentArgs['LCCN'] if viafId and viafId ~= '' and p.viafLink( viafId ) then --VIAF must be present, unsuppressed, & validated table.insert( sections['General'], p.createRow( 'VIAF', viafId, '[https://www.worldcat.org/identities/containsVIAFID/'..viafId..' WorldCat (via VIAF)]', nil, false ) ) if namespace == 0 then worldcatCat = '[[Category:Articles with WorldCat-VIAF identifiers]]' end rct = rct + 1 elseif lccnId and lccnId ~= '' and p.lccnLink( lccnId ) then --LCCN must be present, unsuppressed, & validated local lccnParts = p.splitLccn( lccnId ) if lccnParts and lccnParts[1] ~= 'sh' then local lccnIdFmtd = lccnParts[1]..lccnParts[2]..'-'..lccnParts[3] table.insert( sections['General'], p.createRow( 'LCCN', lccnId, '[https://www.worldcat.org/identities/lccn-'..lccnIdFmtd..' WorldCat (via Library of Congress)]', nil, false ) ) if namespace == 0 then worldcatCat = '[[Category:Articles with WorldCat-LCCN identifiers]]' end end rct = rct + 1 end end --configure Navbox local outString = '' local extrap = true local extra = parentArgs.extralist if extra == nil or extra == '' then extrap = false end if rct > 0 or extrap then local Navbox = require('Module:Navbox') local sectionID = 1 local args = { pid = 'identifiers' } -- #target the list of identifiers if testcases and itemId then args.qid = itemId end --expensive local pencil = require('Module:EditAtWikidata')._showMessage(args) local navboxArgs = { name = 'Authority control', navboxclass = 'authority-control', bodyclass = 'hlist', state = parentArgs.state or 'autocollapse', navbar = 'off' } for _, sectName in ipairs(sectionOrder) do if #sections[sectName] ~= 0 then navboxArgs['group'..sectionID] = sectName navboxArgs['list'..sectionID] = table.concat(sections[sectName]) sectionID = sectionID + 1 end end if extrap then if parentArgs.extragroup then navboxArgs['group'..sectionID] = parentArgs.extragroup else navboxArgs['group'..sectionID] = 'Additional' end navboxArgs['list'..sectionID] = extra sectionID = sectionID + 1 end if navboxArgs.list2 then navboxArgs.title = '[[Help:Authority control|Authority control]]'..pencil else local sect = navboxArgs.group1 if sect == 'General' or sect == 'Other' or sect == 'Additional' then -- Just say "Authority control" with no label if only general or only other IDs are present -- since "general" is redundant and "other" is silly when there's nothing to contrast it with navboxArgs.group1 = '[[Help:Authority control|Authority control]]'..pencil else navboxArgs.group1 = '[[Help:Authority control|Authority control: '..sect..']] '..pencil end end outString = Navbox._navbox(navboxArgs) end --auxCats if rct == 0 or rct >= 25 then if namespace == 0 or testcases then local eCat = 'AC with '..rct..' elements' elementsCat = addCat(eCat) end end if parentArgs.state then if namespace == 0 or testcases then local sCat if parentArgs.state == 'collapsed' then sCat = 'AC using state parameter: collapsed' elseif parentArgs.state == 'expanded' then sCat = 'AC using state parameter: expanded' elseif parentArgs.state == 'autocollapse' then sCat = 'AC using state parameter: autocollapse' else sCat = 'AC using state parameter: other' end stateCat = addCat(sCat) end end local auxCats = worldcatCat..elementsCat..multipleIdCat..suppressedIdCat..suppressedIdCatArts.. deprecatedIdCat..differentOnWDCat..sameOnWDCat..stateCat if testcases then auxCats = mw.ustring.gsub(auxCats, '(%[%[)(Category)', '%1:%2') --for easier checking end --out outString = outString..auxCats if namespace ~= 0 then outString = mw.ustring.gsub(outString, '(%[%[)(Category:Articles)', '%1:%2') --by definition end return outString end return p cd0db2cc5bc4d9d60808eaacdd367d8aacb169ea Module:ResolveEntityId 828 92 200 199 2022-09-04T15:24:53Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local p = {} function p._id(idOrTitle, alt) local function checkId(id) if id and mw.wikibase.entityExists(id) then local sitelink = mw.wikibase.getSitelink(id) if sitelink then return mw.wikibase.getEntityIdForTitle(sitelink) or mw.wikibase.getEntity(id).id end return mw.wikibase.getEntity(id).id else return alt end end if type(idOrTitle) == 'string' then idOrTitle = mw.ustring.upper(mw.ustring.sub(idOrTitle, 1, 1)) .. mw.ustring.sub(idOrTitle, 2) if mw.wikibase.isValidEntityId(idOrTitle) then -- idOrTitle is in the proper format for a Wikidata entity ID return checkId(idOrTitle) else local eid = mw.wikibase.getEntityIdForTitle(idOrTitle) if eid then -- idOrTitle is a title that matches a Wikidata entity local instanceOf = mw.wikibase.getBestStatements(eid, 'P31')[1] --instance of if not instanceOf or instanceOf.mainsnak.datavalue.value.id ~= 'Q4167410' then -- instance-of value is missing or is not "disambiguation" return checkId(eid) end else -- idOrTitle is a title, but no wikidata item exists for that title local rtarget = mw.title.new(idOrTitle).redirectTarget if rtarget then -- title is a Wikipedia redirect return p._id(rtarget.fullText, alt) end end end end return alt end function p.entityid(frame) return p._id(frame.args[1], frame.args[2]) end return p 520d9c0247df2692f8909c86f05c6eb7aab182c0 Template:If empty 10 93 202 201 2022-09-04T15:24:54Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{<includeonly>safesubst:</includeonly>#invoke:If empty|main}}<noinclude>{{Documentation}}</noinclude> 745940b7bdde8a1585c887ee4ee5ce81d98461a4 Module:If empty 828 94 204 203 2022-09-04T15:24:54Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local p = {} function p.main(frame) local args = require('Module:Arguments').getArgs(frame, {wrappers = 'Template:If empty', removeBlanks = false}) local lastk = 0 for k,v in ipairs(args) do if v ~= '' then return v end lastk = k end end return p 4bfc0c7c8bf3b63144db1ea12f2260db00421233 Template:Convert 10 95 206 205 2022-09-04T15:24:54Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{{{{♥|safesubst:}}}#invoke:convert|convert}}</includeonly><noinclude> {{documentation}} <!-- Add categories to the /doc subpage, interwikis to Wikidata, not here --> </noinclude> 952ac4080dc4a427c4a65db9951c8a4f4c91c626 Template:Cite book 10 96 208 207 2022-09-04T15:24:55Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=book }}</includeonly><noinclude> {{documentation}} {{collapse top|TemplateData}} {{Cite book/TemplateData}} {{collapse bottom}} </noinclude> c474cbe5d051e08f516083d594207d449245c717 Template:Cite encyclopedia 10 97 210 209 2022-09-04T15:24:55Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=encyclopaedia }}</includeonly><noinclude> {{documentation}} [[Category:Lua-based templates]] </noinclude> a5fbaa0493d06b11ef4dd711383f9fd5174a4238 Template:Navbox 10 98 212 211 2022-09-04T15:24:55Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:Navbox|navbox}}</includeonly><noinclude> {{Documentation}} </noinclude> fe9b964401f895918ee4fe078678f1722a3c41ec Template:Other uses 10 99 214 213 2022-09-04T15:24:55Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#invoke:other uses|otheruses}}<noinclude>{{documentation}}</noinclude> 3bd6c67c92b11a14d2e58145b096152fbc066580 Template:Sfn 10 100 216 215 2022-09-04T15:24:56Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:Footnotes|sfn|template=sfn}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using sfn with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Sfn]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | 2 | 3 | 4 | 5 | ignore-err | loc | p | page | pages | postscript | pp | ps | ref | Ref }}<noinclude> {{documentation}} </noinclude> eab6519b2a87e18dc40f39343c71f5848977cc93 Template:SfnRef 10 101 218 217 2022-09-04T15:24:56Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{safesubst<noinclude />:#invoke:Footnotes|sfnref}}<noinclude> {{documentation}} </noinclude> 56e03dd26fcd9edbe71a96b5c5c84198863b964b Module:Footnotes 828 102 220 219 2022-09-04T15:24:56Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain require('Module:No globals'); local getArgs = require ('Module:Arguments').getArgs; --[[--------------------------< A R G S _ D E F A U L T >------------------------------------------------------ a table to specify initial values. ]] local args_default = { bracket_left = '', bracket_right = '', bracket_year_left = '', bracket_year_right = '', postscript = '', page = '', pages = '', location = '', page_sep = ", p.&nbsp;", pages_sep = ", pp.&nbsp;", ref = '', template = 'harv', -- if template name not provided in {{#invoke:}} use this }; --[[--------------------------< T A R G E T _ C H E C K >------------------------------------------------------ look for anchor_id (CITEREF name-list and year or text from |ref=) in anchor_id_list the 'no target' error may be suppressed with |ignore-err=yes when target cannot be found because target is inside a template that wraps another template; 'multiple targets' error may not be suppressed ]] local function target_check (anchor_id, args) local namespace = mw.title.getCurrentTitle().namespace; local anchor_id_list_module = mw.loadData ('Module:Footnotes/anchor_id_list'); local anchor_id_list = anchor_id_list_module.anchor_id_list; local article_whitelist = anchor_id_list_module.article_whitelist; local template_list = anchor_id_list_module.template_list; local whitelist_module = mw.loadData ('Module:Footnotes/whitelist'); local whitelist = whitelist_module.whitelist; local special_patterns = whitelist_module.special_patterns; local DNB_special_patterns = whitelist_module.DNB_special_patterns; local DNB_template_names = whitelist_module.DNB_template_names; if 10 == namespace then return ''; -- automatic form of |no-tracking=yes; TODO: is this too broad? end local tally = anchor_id_list[anchor_id]; -- nil when anchor_id not in list; else a tally local msg; local category; if not tally then if args.ignore then return ''; -- if ignore is true then no message, no category end if article_whitelist and article_whitelist[anchor_id] then -- if an article-local whitelist and anchor ID is in it return ''; -- done end local wl_anchor_id = anchor_id; -- copy to be modified to index into the whitelist if args.year then -- for anchor IDs created by this template (not in |ref=) that have a date if args.year:match ('%d%l$') or -- use the date value to determine if we should remove the disambiguator args.year:match ('n%.d%.%l$') or args.year:match ('nd%l$') then wl_anchor_id = wl_anchor_id:gsub ('%l$', ''); -- remove the disambiguator end end local t_tbl = whitelist[wl_anchor_id]; -- get list of templates associated with this anchor ID if t_tbl then -- when anchor ID not whitelisted t_tbl is nil for _, t in ipairs (t_tbl) do -- spin through the list of templates associated with this anchor ID if template_list[t] then -- if associated template is found in the list of templates in the article return ''; -- anchor ID is whitlisted and article has matching template so no error end end end for _, pattern in ipairs (special_patterns) do -- spin through the spcial patterns and try to match if anchor_id:match (pattern) then return ''; end end for _, dnb_t in ipairs (DNB_template_names or {}) do -- getting desparate now, are there any DNB templates? DNB_template_names may be nil; empty table prevents script error if template_list[dnb_t] then -- if the article has this DNB template for _, pattern in ipairs (DNB_special_patterns) do -- spin through the DNB-specifiec wildcard patterns if anchor_id:match (pattern) then -- and attempt a match return ''; -- found a match end end end end msg = 'no target: ' .. anchor_id; -- anchor_id not found category = '[[Category:Harv and Sfn no-target errors]]'; elseif 1 < tally then msg = 'multiple targets (' .. tally .. '×): ' .. anchor_id; -- more than one anchor_id in this article category = 0 == namespace and '[[Category:Harv and Sfn multiple-target errors]]' or ''; -- only categorize in article space return '<span class="error harv-error" style="display: inline; font-size:100%"> ' .. args.template .. ' error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category; end -- category = 0 == namespace and '[[Category:Harv and Sfn template errors]]' or ''; -- only categorize in article space category = 0 == namespace and category or ''; -- only categorize in article space --use this version to show error messages -- return msg and '<span class="error harv-error" style="display: inline; font-size:100%"> ' .. args.template .. ' error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category or ''; --use this version to hide error messages return msg and '<span class="error harv-error" style="display: none; font-size:100%"> ' .. args.template .. ' error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category or ''; end --[[--------------------------< I S _ Y E A R >---------------------------------------------------------------- evaluates param to see if it is one of these forms with or without lowercase letter disambiguator: YYYY n.d. nd c. YYYY YYYY–YYYY (separator is endash) YYYY–YY (separator is endash) return true when param has a recognized form; false else ]] local patterns_date= { '^%d%d%d%d?%l?$', '^n%.d%.%l?$', '^nd%l?$', '^c%. %d%d%d%d?%l?$', '^%d%d%d%d–%d%d%d%d%l?$', '^%d%d%d%d–%d%d%l?$', } local function is_year (param, args) args.year = ''; -- used for harv error; for _, pattern in ipairs (patterns_date) do if mw.ustring.match (param, pattern) then args.year = param; -- used for harv error; return true; end end end --[[--------------------------< C O R E >---------------------------------------------------------------------- returns an anchor link (CITEREF) formed from one to four author names, year, and insource location (|p=, |pp=, loc=) ]] local function core( args ) local result; local err_msg = '' if args.P5 ~= '' then if is_year (args.P5, args) then result = table.concat ({args.P1, ' et al. ', args.bracket_year_left, args.P5, args.bracket_year_right}); else args.P5 = ''; -- when P5 not a year don't include in anchor result = table.concat ({args.P1, ' et al.'}); -- and don't render it end elseif args.P4 ~= '' then if is_year (args.P4, args) then result = table.concat ({args.P1, ', ', args.P2, ' &amp; ', args.P3, ' ', args.bracket_year_left, args.P4, args.bracket_year_right}); -- three names and a year else result = table.concat ({args.P1, ' et al.'}); -- four names end elseif args.P3 ~= '' then if is_year (args.P3, args) then result = table.concat ({args.P1, ' &amp; ', args.P2, ' ', args.bracket_year_left, args.P3, args.bracket_year_right}); -- two names and a year else result = table.concat ({args.P1, ', ', args.P2, ' ', ' &amp; ', args.P3}); -- three names end elseif args.P2 ~= '' then if is_year (args.P2, args) then result = table.concat ({args.P1, ' ', args.bracket_year_left, args.P2, args.bracket_year_right}); -- one name and year else result = table.concat ({args.P1, ' &amp; ', args.P2}); -- two names end else result = args.P1; -- one name end -- when author-date result ends with a dot (typically when the last positional parameter holds 'n.d.') -- and when no in-source location (no |p=, |pp=, or |loc=) -- and when the first or only character in args.postscript is a dot -- remove the author-date result trailing dot -- the author-date result trailing dot will be replaced later with the content of args.postscript (usually a dot) if ('.' == result:sub(-1)) and ('.' == args.postscript:sub(1)) and ('' == args.page) and ('' == args.pages) and ('' == args.location) then result = result:gsub ('%.$', ''); end if args.ref ~= 'none' then local anchor_id; if args.ref ~= '' then anchor_id = mw.uri.anchorEncode (args.ref); err_msg = target_check (anchor_id, args); result = table.concat ({'[[#', anchor_id, '|', result, ']]'}); else anchor_id = mw.uri.anchorEncode (table.concat ({'CITEREF', args.P1, args.P2, args.P3, args.P4, args.P5})); err_msg = target_check (anchor_id, args); result = table.concat ({'[[#', anchor_id, '|', result, ']]'}); end end if args.page ~= '' then result = table.concat ({result, args.page_sep, args.page}); elseif args.pages ~= ''then result = table.concat ({result, args.pages_sep, args.pages}); end if args.location ~= '' then result = table.concat ({result, ', ', args.location}); end result = table.concat ({args.bracket_left, result, args.bracket_right, args.postscript}):gsub ('%s+', ' '); -- strip redundant spaces return result .. err_msg; end --[[--------------------------< H Y P H E N _ T O _ D A S H >-------------------------------------------------- Converts a hyphen to a dash under certain conditions. The hyphen must separate like items; unlike items are returned unmodified. These forms are modified: letter - letter (A - B) digit - digit (4-5) digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5) letterdigit - letterdigit (A1-A5) (an optional separator between letter and digit is supported – a.1-a.5 or a-1-a-5) digitletter - digitletter (5a - 5d) (an optional separator between letter and digit is supported – 5.a-5.d or 5-a-5-d) any other forms are returned unmodified. str may be a comma- or semicolon-separated list This code copied from Module:Citation/CS1. The only modification is to require Module:Citation/CS1/Utilities so that it has access to the functions is_set() and has_accept_as_written() ]] local function hyphen_to_dash( str ) local utilities = require ('Module:Citation/CS1/Utilities'); -- only modification so that this function has access to is_set() and has_accept_as_written() if not utilities.is_set (str) then return str; end local accept; -- Boolean str = str:gsub ('&[nm]dash;', {['&ndash;'] = '–', ['&mdash;'] = '—'}); -- replace &mdash; and &ndash; entities with their characters; semicolon mucks up the text.split str = str:gsub ('&#45;', '-'); -- replace HTML numeric entity with hyphen character str = str:gsub ('&nbsp;', ' '); -- replace &nbsp; entity with generic keyboard space character local out = {}; local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any for _, item in ipairs (list) do -- for each item in the list item, accept = utilities.has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators if item:match ('^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$') or -- letterdigit hyphen letterdigit (optional separator between letter and digit) item:match ('^%d+[%.%-]?%a+%s*%-%s*%d+[%.%-]?%a+$') or -- digitletter hyphen digitletter (optional separator between digit and letter) item:match ('^%d+[%.%-]%d+%s*%-%s*%d+[%.%-]%d+$') or -- digit separator digit hyphen digit separator digit item:match ('^%d+%s*%-%s*%d+$') or -- digit hyphen digit item:match ('^%a+%s*%-%s*%a+$') then -- letter hyphen letter item = item:gsub ('(%w*[%.%-]?%w+)%s*%-%s*(%w*[%.%-]?%w+)', '%1–%2'); -- replace hyphen, remove extraneous space characters else item = mw.ustring.gsub (item, '%s*[–—]%s*', '–'); -- for endash or emdash separated ranges, replace em with en, remove extraneous whitespace end end table.insert (out, item); -- add the (possibly modified) item to the output table end local temp_str = ''; -- concatenate the output table into a comma separated string temp_str, accept = utilities.has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out if accept then temp_str = utilities.has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value return temp_str; else return temp_str; -- else, return assembled temp_str end end --[[--------------------------< A R G S _ F E T C H >--------------------------------------------------------- Because all of the templates share a common set of parameters, a single common function to fetch those parameters from frame and parent frame. ]] local function args_fetch (frame, ps) local args = args_default; -- create a copy of the default table local pframe = frame:getParent(); -- point to the template's parameter table for k, v in pairs (frame.args) do -- override defaults with values provided in the #invoke: if any args[k] = v; end args.postscript = pframe.args.postscript or pframe.args.ps or ps; if 'none' == args.postscript then args.postscript = ''; end args.page = pframe.args.p or pframe.args.page or ''; args.pages = pframe.args.pp or pframe.args.pages or ''; args.pages = ('' ~= args.pages) and hyphen_to_dash (args.pages) or ''; args.location = pframe.args.loc or ''; args.ref = pframe.args.ref or pframe.args.Ref or ''; args.ignore = ('yes' == pframe.args['ignore-false-positive']) or ('yes' == pframe.args['ignore-err']); for i, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- loop through the five positional parameters and trim if set else empty string args[v] = (pframe.args[i] and mw.text.trim (pframe.args[i])) or ''; end if args.P5 and not is_year (args.P5, args) then local i = 6; -- initialize the indexer to the sixth positional parameter while pframe.args[i] do -- in case there are too many authors loop through the authors looking for a year local v = mw.text.trim (pframe.args[i]); -- trim if is_year (v, args) then -- if a year args.P5 = v; -- overwrite whatever was in args.P5 with year break; -- and abandon the search end i = i + 1; -- bump the indexer end end return args; end --[[--------------------------< H A R V A R D _ C I T A T I O N >---------------------------------------------- common entry point for: {{harvard citation}} aka {{harv}} {{Harvard citation no brackets}} aka {{harvnb}} {{harvcol}} {{harvcolnb}} {{harvcoltxt}} {{Harvard citation text}} aka {{harvtxt}} {{Harvp}} Distinguishing features (brackets and page separators) are specified in this module's {{#invoke}} in the respective templates. ]] local function harvard_citation (frame) local args = args_fetch (frame, ''); -- get the template and invoke parameters; default postscript is empty string return core (args); end --[[--------------------------< S T R I P _ U R L >------------------------------------------------------------ used by sfn() and sfnm(). This function fixes an issue with reference tooltip gadget where the tooltip is not displayed when an insource locator (|p=, |pp=, |loc=) has an external wikilink that contains a # character strip uri-reserved characters from urls in |p=, |pp-, and |loc= parameters The researved characters are: !#$&'()*+,/:;=?@[] ]] local function strip_url (pages) local escaped_uri; if not pages or ('' == pages) then return pages; end for uri in pages:gmatch ('%[(%a[%w%+%.%-]*://%S+)') do -- for each external link get the uri escaped_uri = uri:gsub ("([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ); -- save a copy with lua pattern characters escaped uri = uri:gsub ("[!#%$&'%(%)%*%+,/:;=%?@%[%]%.%%]", ''); -- remove reserved characters and '%' because '%20' (space character) is a lua 'invalid capture index' pages = pages:gsub (escaped_uri, uri, 1); -- replace original uri with the stripped version end return pages; end --[[--------------------------< S F N >------------------------------------------------------------------------ entry point for {{sfn}} and {{sfnp}} ]] local function sfn (frame) local args = args_fetch (frame, '.'); -- get the template and invoke parameters; default postscript is a dot local result = core (args); -- go make a CITEREF anchor -- put it all together and then strip redundant spaces local name = table.concat ({'FOOTNOTE', args.P1, args.P2, args.P3, args.P4, args.P5, strip_url (args.page), strip_url (args.pages), strip_url (args.location)}):gsub ('%s+', ' '); return frame:extensionTag ({name='ref', args={name=name}, content=result}); end --[[--------------------------< S F N M >---------------------------------------------------------------------- common entry point for {{sfnm}} and {{sfnmp}} Distinguishing features (brackets) are specified in this module's {{#invoke}} in the respective templates. ]] local function sfnm (frame) local args = args_default; -- create a copy of the default table local pframe = frame:getParent(); -- point to the template's parameter table local n = 1; -- index of source; this is the 'n' in na1, ny, etc local first_pnum = 1; -- first of a pair of positional parameters local second_pnum = 2; -- second of a pair of positional parameters local last_ps = 0; -- index of the last source with |nps= set local last_index = 0; -- index of the last source; these used to determine which of |ps= or |nps= will terminate the whole rendering local out = {}; -- table to hold rendered sources local footnote = {'FOOTNOTE'}; -- all author, date, insource location stuff becomes part of the reference's footnote id; added as we go for k, v in pairs (frame.args) do -- override defaults with values provided in the #invoke: if any args[k] = v; end while true do if not pframe.args[table.concat ({n, 'a1'})] and not pframe.args[first_pnum] then break; -- no na1 or matching positional parameter so done end if pframe.args[table.concat ({n, 'a1'})] then -- does this source use named parameters? for _, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- initialize for this source args[v] = ''; end for i, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- extract author and year parameters for this source args[v] = pframe.args[table.concat ({n, 'a', i})] or ''; -- attempt to assign author name if '' == args[v] then -- when there wasn't an author name args[v] = pframe.args[table.concat ({n, 'y'})] or ''; -- attempt to assign year break; -- done with author/date for this source end end else -- this source uses positional parameters args.P1 = mw.text.trim (pframe.args[first_pnum]); -- yes, only one author supported args.P2 = (pframe.args[second_pnum] and mw.text.trim (pframe.args[second_pnum])) or ''; -- when positional author, year must also be positional for _, v in ipairs ({'P3', 'P4', 'P5'}) do -- blank the rest of these for this source args[v] = ''; end first_pnum = first_pnum + 2; -- source must use positional author and positional year second_pnum = first_pnum + 1; -- bump these for possible next positional source end args.postscript = pframe.args[table.concat ({n, 'ps'})] or ''; if 'none' == args.postscript then -- this for compatibility with other footnote templates; does nothing args.postscript = ''; end args.ref = pframe.args[table.concat ({n, 'ref'})] or ''; -- alternate reference for this source args.page = pframe.args[table.concat ({n, 'p'})] or ''; -- insource locations for this source args.pages = pframe.args[table.concat ({n, 'pp'})] or ''; args.pages = ('' ~= args.pages) and hyphen_to_dash (args.pages) or ''; args.location = pframe.args[table.concat ({n, 'loc'})] or ''; args.ignore = ('yes' == pframe.args[table.concat ({n, 'ignore-false-positive'})]) or ('yes' == pframe.args[table.concat ({n, 'ignore-err'})]); table.insert (out, core (args)); -- save the rendering of this source for k, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- create the FOOTNOTE id if '' ~= args[v] then table.insert (footnote, args[v]); end end for k, v in ipairs ({'page', 'pages', 'location'}) do -- these done separately so that we can strip uri-reserved characters from extlinked page numbers if '' ~= args[v] then table.insert (footnote, strip_url (args[v])) end end last_index = n; -- flags used to select terminal postscript from nps or from end_ps if '' ~= args.postscript then last_ps = n; end n = n+1; -- bump for the next one end local name = table.concat (footnote):gsub ('%s+', ' '); -- put the footnote together and strip redundant space args.end_ps = pframe.args.postscript or pframe.args.ps or '.'; -- this is the postscript for the whole not for the individual sources if 'none' == args.end_ps then -- not an original sfnm parameter value; added for compatibility with other footnote templates args.end_ps = ''; end local result = table.concat ({table.concat (out, '; '), (last_index == last_ps) and '' or args.end_ps}); return frame:extensionTag ({name='ref', args={name=name}, content=result}); end --[[--------------------------< S F N R E F >------------------------------------------------------------------ implements {{sfnref}} ]] local function sfnref (frame) local args = getArgs (frame); local out = {}; for i=1, 5 do -- get the first five args if there are five args if args[i] then out[i] = args[i]; else break; -- less than 5 args break out end end if 5 == #out then -- when we have seen five args there may bemore local i = 6; -- initialize the indexer to the sixth positional parameter while args[i] do -- in case there are too many authors loop through the authors looking for a year if is_year (args[i], args) then -- if a year out[5] = args[i]; -- overwrite whatever was in args[5] with year break; -- and abandon the search end i = i + 1; -- bump the indexer end end return mw.uri.anchorEncode ('CITEREF' .. table.concat (out)); end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { harvard_citation = harvard_citation, sfn = sfn, sfnm = sfnm, sfnref = sfnref, }; 1900e2ea7aff0f4023cd9a8f39ece502cc07e045 Module:Footnotes/anchor id list 828 103 222 221 2022-09-04T15:24:57Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain require('Module:No globals'); local data = mw.loadData ('Module:Footnotes/anchor id list/data'); local whitelist = mw.loadData ('Module:Footnotes/whitelist'); local Lang_obj = mw.language.getContentLanguage(); -- used by template_list_add() to uppercase first letter of template name TODO: better way to do that? local redirects_date = { ['date'] = true, ['datetomos'] = true, ['formatdate'] = true, ['isotodmymdy'] = true, ['isotomos'] = true, } local redirects_patent = { -- special case cs1-like templates because uses different parameters for name and date in anchor ID ['Cite patent'] = true, ['Citeref patent'] = true, ['Ref patent'] = true, } local redirects_sfnref = { ['sfnref'] = true, ['harvid'] = true, } local aliases_author = { -- these use pseudo-patterns in the same way as cs1|2; '#' represents 1 or more enumerator digits 'last#', 'author#', 'surname#', 'author-last#', 'author#-last', 'subject#', 'host#', } local aliases_contributor = { 'contributor#', 'contributor-last#', 'contributor#-last', 'contributor-surname#', 'contributor#-surname', } local aliases_editor = { 'editor#', 'editor-last#', 'editor#-last', 'editor-surname#', 'editor#-surname', } local aliases_harvc_author = { 'last#', 'author#', } local aliases_inventor = { -- cite patent 'inventor#', 'inventor-last#', 'inventor#-last', 'inventor-surname#', 'inventor#-surname', 'invent#', 'invent-#', } local alias_patterns_date = { -- normal lua patterns for most cs1|2-like templates '|%s*year%s*=%s*', '|%s*date%s*=%s*', '|%s*publication%-?date%s*=%s*', '|%s*air%-?date%s*=%s*', } local alias_patterns_harvc_date = { -- normal lua patterns for harvc template '|%s*anchor%-year%s*=%s*', '|%s*year%s*=%s*', } local alias_patterns_patent_date = { -- normal lua patterns for cite patent templates '|%s*issue%-date%s*=%s*', '|%s*gdate%s*=%s*', '|%s*publication%-date%s*=%s*', '|%s*pubdate%s*=%s*', } local patterns_date = { -- normal lua patterns '(%d%d%d%d–%d%d%d%d%l?)$', -- YYYY–YYYY four-digit year range at end (Season YYYY–YYYY); with or without dab '^(%d%d%d%d–%d%d%l?)$', -- YYYY–YY two-digit year range; with or without dab '^(c%. %d%d%d%d?%l?)$', -- three- or four-digit circa year; with or without dab '(%d%d%d%d?%l?)$', -- three- or four-digit year at end of date (dmy or mdy); with or without dab '^(%d%d%d%d?%l?)', -- three- or four-digit year at beginning of date (ymd or YYYY); with or without dab '^(n%.d%.%l?)$', -- 'no date' with dots; with or without dab '^(nd%l?)$', -- 'no date' without dots; with or without dab } local patterns_tags = { '<nowiki>.-</nowiki>', '<!%-%-.-%-%->', '<pre>.-</pre>', '<syntaxhighlight.->.-</syntaxhighlight>', '<source.->.-</source>', -- deprecated alias of syntaxhighlight tag } local template_skip = { -- templates to be skipped for whatever reason; mostly because they resemble cs1-like templates ['Citation-attribution'] = true, } local Article_content; local anchor_id_list = {}; -- exported tables local template_list = {}; local article_whitelist = {}; --[[--------------------------< A R T I C L E _ C O N T E N T _ G E T >---------------------------------------- get article content, remove certain html-like tags and their content so that this code doesn't include any citation templates inside the tags as valid tagets; they are not. ]] local function article_content_get () if not Article_content then Article_content = mw.title.getCurrentTitle():getContent() or ''; -- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625 for _, tag in ipairs (patterns_tags) do Article_content = Article_content:gsub (tag, ''); -- remove certain html-like tags and their content end end end --[[--------------------------< S F N R E F _ G E T >---------------------------------------------------------- make an anchor id from the contents of {{sfnref}} or {{harvid}}. this function assumes that {{sfnref}} and {{harvid}} are correctly formed. ]] local function sfnref_get (template) template = template:gsub ('{{%s*(.-)%s*}}', '%1'); -- strip bounding template markup and trim local parts = mw.text.split (template, '%s*|%s*'); -- split at the pipe and remove extraneous space characters local anchor_id = {}; if redirects_sfnref[parts[1]:lower()] then anchor_id[1] = 'CITEREF'; else return nil; -- not an sfnref or harvid template end local i = 2; -- indexer into parts{} table local j = 2; -- indexer into anchor_id{} table which already has 'CITEREF' at [1] while parts[i] and 7 > j do -- loop through what should be just positional parameters for names and year (2-6 four names and a date) if not parts[i]:find ('=') then -- look for equal sign (named paraneter in a template that doesn't support named parameters) anchor_id[j] = parts[i]; -- positional parameters are saved j = j+1; -- bump the anchor_id{} indexer end i = i+ 1; -- bump the parts{} indexer end return table.concat (anchor_id, ''); end --[[--------------------------< D A T E _ G E T >-------------------------------------------------------------- extract year from one of |year=, |date=, |publicationdate=, or |publication-date in that order. Does not error check (that is left to the cs1|2 templates to do) also gets date from |<date alias>={{date|...}} ]] local function date_get (template, aliases) local date; local rvalue; for _, pattern in ipairs (aliases) do -- spin through the date alias patterns rvalue = tostring(template):match (pattern); -- is this |<date alias>= used (tostring() because something makes match() think template is a table) if rvalue then rvalue = tostring(template):match (pattern .. '(%b{})'); -- is rvalue a template? if rvalue then rvalue = rvalue:gsub ('{{%s*(.-)%s*}}', '%1'); -- strip bounding template markup and trim local parts = mw.text.split (rvalue, '%s*|%s*'); -- split at the pipe and remove extraneous space characters if redirects_date[parts[1]:lower()] then -- if parts[1] names {{date}} or redirect rvalue = parts[2]; -- assume that date template is properly formed, first positional parameter is the date else return ''; -- |date= holds some other template than {{date}} or redirect end else rvalue = template:match (pattern .. '([^|}]+)'); if rvalue then -- if rvalue is something rvalue = mw.text.trim (rvalue); -- trim it end if not rvalue or '' == rvalue then -- if rvale was nothing or trimed to nothing rvalue = nil; -- ensure that it is unset so we can try the next parameter in the list end end if rvalue then for _, pattern in ipairs (patterns_date) do -- spin through the recognized date formats date = rvalue:match (pattern); -- attempt to extract year portion according to the pattern if date then return date; -- matched so return; end end break; -- found a date but it was malformed so abandon end end end return ''; -- no date param or date param doesn't hold a recognized date; empty string for concatenation end --[[--------------------------< V N A M E S _ G E T >---------------------------------------------------------- extract names from |vauthors= or |veditors=; there is no |vcontributors= parameter. splits the v parameter value at the comma; correctly handles accept-as-witten markup when used to wrap a comma- separated names (corporate) ]] local function vnames_get (params, vparam) local vnames = {}; -- first four author or editor names go here local split = {}; -- temp table to assist in decoding accept-as-witten-markup if params[vparam] then -- test for |vauthors= or |veditor= split = mw.text.split (params[vparam], '%s*,%s*'); -- this will separate portions of ((Black, Brown, White, an Co.)) local i = 1; -- an indexer while split[i] do if split[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of comma-separated accept-as-witten; this segment has the opening doubled parens local name = split[i]; i=i+1; -- bump indexer to next segment while split[i] do name = name .. ', ' .. split[i]; -- concatenate with previous segments if split[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parens break; -- and done reassembling so end i=i+1; -- bump indexer end table.insert (vnames, name); -- and add accept-as-witten name to the vnames table else table.insert (vnames, split[i]); -- and add name to the vnames table end i=i+1; -- bump indexer if 5 == i then break; end -- limit to four names end for i, vname in ipairs (vnames) do if not vname:match ('%(%(.-%)%)') then -- without accept-this-value-as-written markup vnames[i] = vname:gsub ('(.-)%s+%u+$', '%1'); -- extract and save surname(s) end end for i, vname in ipairs (vnames) do -- repeat, this time for accept-this-value-as-written markup vnames[i] = vname:gsub ('%(%((.-)%)%)', '%1'); -- remove markup if present and save the whole name end end return 0 ~= #vnames and table.concat (vnames) or nil -- return a concatenation of the vnames; nil else end --[[--------------------------< N A M E S _ G E T >------------------------------------------------------------ cs1|2 makes anchor id from contributor, author, or editor name-lists in that order get the names from the cs1|2 template; if there are no contributor names, try author names, then try editor names. returns concatenated names in enumeration order when successful; nil else empty name (nameholding parameter n is present without value) and missing name (nameholding parameter n is not present) are included as empty string with all other names ]] local function names_get (params, aliases_list) local names = {}; -- first four author or editor names go here local enum_alias; -- alias with '#' replaced with a digit for enum=1, 4 do -- four names only for i, alias in ipairs (aliases_list) do if not names[enum] then -- hanven't found a previous alias with this [enum]? see if we can find this alias with this enum enum_alias = alias:gsub ('#', enum); -- replace '#' to make 'lastn' if 1 == enum then -- because |last= and last1= are exact aliases if params[enum_alias] then -- test |last1= first names[enum] = params[enum_alias]; -- found so save the value assigned to |last1= break; -- next enum else enum_alias = alias:gsub ('#', ''); -- replace '#' to make 'last' if params[enum_alias] then names[enum] = params[enum_alias]; -- found so save the value assigned to |last= break; -- next enum end end else -- here for enum 2, 3, 4 if params[enum_alias] then names[enum] = params[enum_alias]; -- found so save the value assigned to |lastn= break; -- next enum end end end end end for enum=1, 4 do -- spin through the names table and local name = names[enum]; if not name then -- when nameholding parameter n is not present (nil) name = ''; -- convert to empty string for concatenation end name = name:gsub('%(%((.-)%)%)', '%1'); -- remove accept-as-written markup if present names[enum] = name; -- save the modified name end local name_str = table.concat (names); -- concatenate the names return '' ~= name_str and name_str or nil; -- return the concatenation if not empty string; nil else end --[[--------------------------< T E M P L A T E _ S T R I P >-------------------------------------------------- removes the citation or havrc template's {{ and }} markup then removes, in whole, any templates found inside the citation or harvc template. Templates are not allowed in parameters that are made part of COinS metadata; yet, they will appear. cs1|2 does not see the template markup but instead sees the result of the template as html. cs1|2 strips the html which leaves the displayed value for the anchor id. We can't do that here so, because templates aren't allowed in parameters, we simply discard any templates found in the cs1|2 template. this may leave a |lastn= parameter empty which will be treated as if it were really empty as cs1|2 do (three authors, |last2= empty -> CITEREFLast1Last3YYYY (the harv and sfn render: 'Last1, & Last3 YYYY' with CITEREFLast1Last3YYYY). ]] local function template_strip (template) template = template:gsub ('^{{%s*', ''):gsub ('%s*}}$', '', 1); -- remove outer {{ and }} (cs1|2 template delimiters with trailing/leading whitespace) template = template:gsub ('%b{}', ''); -- remove any templates from the cs1|2 template return template; end --[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >---------------------------------- Returns a string where all of lua's magic characters have been escaped. This is important because functions like string.gsub() treat their pattern and replace strings as patterns, not literal strings. ]] local function escape_lua_magic_chars (argument) argument = argument:gsub("%%", "%%%%"); -- replace % with %% argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other lua magic pattern characters return argument; end --[=[-------------------------< W I K I L I N K _ S T R I P >-------------------------------------------------- Wikilink markup does not belong in an anchor id and can / does confuse the code that parses apart citation and harvc templates so here we remove any wiki markup: [[link|label]] -> label [[link]] -> link ]=] local function wikilink_strip (template) for wikilink in template:gmatch ('%[%b[]%]') do -- get a wikilink template = template:gsub ('%[%b[]%]', '__57r1P__', 1); -- install a marker if wikilink:match ('%[%[.-|(.-)%]%]') then wikilink = wikilink:match ('%[%[.-|(.-)%]%]'); -- extract label from complex [[link|label]] wikilink else wikilink = wikilink:match ('%[%[(.-)%]%]'); -- extract link from simple [[link]] wikilinks end wikilink = escape_lua_magic_chars (wikilink); -- in case there are lua magic characters in wikilink template = template:gsub ('__57r1P__', wikilink, 1); -- replace the marker with the appropriate text end return template; end --[[--------------------------< T E M P L A T E _ N A M E _ G E T >-------------------------------------------- return the citation or harvc template's name; convert to lower case and trim leading and trailing whitespace; when the template is a sandbox the subpage portion of the template name is omitted from the returned template name {{Cite book/new |...}} returns cite book ]] local function template_name_get (template) local template_name = template:match ('^{{%s*([^/|}]+)'); -- get template name; ignore subpages ~/new, ~/sandbox; parser functions if not template_name or template_name:match ('^#') then -- parser functions, magic words don't count as templates return nil; -- could not get template name from (possibly corrupt) template; extraneous opening { mid template can cause this; end; template_name = template_name:gsub ('%s*$', ''); -- trim trailing whitespace; leading whitespace already removed return Lang_obj:ucfirst (template_name); -- first character in template name must be uppercase (same as canonical template name) TODO: better way to do this? end --[[--------------------------< T E M P L A T E _ P A R A M S _ G E T >---------------------------------------- parse apart a template's parameters and store in the params table where key is the parameter's name and value is the parameter's value; empty parameters are not saved ]] local function template_params_get (template, params_t) template = wikilink_strip (template); -- because piped wikilinks confuse code that builds params_t{} and because wikilinks not allowed in an anchor id -- strip templates after getting |ref= value because |ref={{sfnref}} and |ref={{harvid}} are allowed template = template_strip (template); -- because template markup can confuse code that builds params_t{} and because templates in name parameters are not allowed local temp_t = mw.text.split (template, '%s*|%s*'); --split on the pipe for _, param in ipairs (temp_t) do if param:find ('=', 1, true) then -- a named parameter? local k, v = param:match ('%s*([^=]-)%s*=%s*([^|}]+)'); if v then -- there must be a value if '' ~= v and not v:match ('^%s$') then -- skip when value is empty string or only whitespace params_t[k] = mw.text.trim (v); -- add trimmed value else end end end end end --[[--------------------------< C I T E R E F _ M A K E _ H A R V C >------------------------------------------ makes anchor_id from {{harvc}} or redirects ]] local function anchor_id_make_harvc (template) local date = date_get (template, alias_patterns_harvc_date); -- get date; done here because might be in {{date}}; return date if valid; empty string else local anchor_id; local params = {}; -- table of harvc parameters local id; -- custom anchor id for this {{harvc}} template id = template:match ('|%s*id%s*=%s*(%b{})'); -- in case |id={{sfnref}}; done here because templates will be stripped template_params_get (template, params); -- build a table of template parameters and their values; this strips wikilinks and templates if id then -- when set is {{sfnref}} or {{harvid}} template return sfnref_get (id); -- returns content of {{sfnref}} or {{harvid}}; nil else end if params.id then -- custom anchor for this {{harvc}} template (text) return params.id; -- |id= value as written end anchor_id = names_get (params, aliases_harvc_author); -- get the harvc contributor names if anchor_id then -- if names were gotten return 'CITEREF' .. anchor_id .. date; end return nil; -- no names; no anchor_id end --[[--------------------------< A N C H O R _ I D _ M A K E _ W R A P P E R >---------------------------------- for wrapper templates inspect externally visible |ref= to decide what to do: |ref= - empty or missing: get names and date from whitelist defaults; override defaults from externally visible template parameters |ref=harv - same as empty or missing |ref={{SfnRef|name|name|name|name|year}} - assemble an anchor id from {{sfnref}} positional parameters |ref={{Harvid|name|name|name|name|year}} - assemble an anchor id from {{harvid}} positional parameters |ref=none - skip; do nothing because an anchor id intentionally suppressed; TODO: keep with a type code of '0'? |ref=<text> - save param value because may match an anchor id override value in {{harv}} template |ref= parameter or {{harvc}} |id= parameter ]] local function anchor_id_make_wrapper (template) local ref; -- content of |ref= local template_name; -- name of the template local anchor_id; -- the assembled anchor id from this template local date; local name_default; local date_default; local vol; local params = {}; -- table of template parameters template_name = template_name_get (template); -- get first char uppercase trimmed template name; ignore subpages ~/new, ~/sandbox if not template_name or template_skip[template_name] then return nil; -- could not extract template name from (possibly corrupted) template (extraneous opening { in the template will cause this) end date = date_get (template, alias_patterns_date); -- get date; done here because might be in {{date}} -- if '' == date then -- date = whitelist.wrapper_templates[template_name][2] or ''; -- no externally visible date so get default date -- end ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}} because we will strip templates from the wrapper template if not ref then if template:match ('|%s*ref%s*=([^|}]+)') then -- |ref={{template}} not found; if there is a |ref= param with an assigned value ref = template:match ('|%s*ref%s*=([^|}]+)'); -- get the value; whitespace is a 'value' if ref then -- nil when |ref=|... or when |ref=}} (no spaces between assignment operator and pipe or closing brace) ref = mw.text.trim (ref); -- something, could be just whitespace, so trim leading / trailing whitespace if '' == ref then -- trimming a string of whitespace makes an empty string ref = nil; -- make empty ref same as missing ref end end end end template_params_get (template, params); -- build a table of template parameters and their values if whitelist.wrapper_templates[template_name][1] then -- is this wrapper a simple-default wrapper? name_default = whitelist.wrapper_templates[template_name][1]; -- get the default names date_default = whitelist.wrapper_templates[template_name][2]; -- get the default date else vol = params['volume'] or 'default'; if not whitelist.wrapper_templates[template_name][vol] then -- make sure this volume exists vol = 'default'; -- doesn't exist, use default volume end name_default = whitelist.wrapper_templates[template_name][vol][1]; -- get the default names date_default = whitelist.wrapper_templates[template_name][vol][2]; -- get the default date end if 'harv' == ref or not ref then -- |ref=harv specified or |ref= missing or empty anchor_id = names_get (params, aliases_contributor) or -- get contributor, author, or editor names names_get (params, aliases_author) or vnames_get (params, 'vauthors') or -- |vauthors= names_get (params, aliases_editor) or vnames_get (params, 'veditors') or -- |veditors= name_default; -- default names from whitelist -- whitelist.wrapper_templates[template_name][1]; -- default names from whitelist if '' == date then -- if date not provided in the template date = date_default; -- use the default date from whitelist end if anchor_id then -- if names were gotten anchor_id = 'CITEREF' .. anchor_id .. date; end elseif ref:match ('%b{}') then -- ref holds a template anchor_id = sfnref_get (ref); -- returns content of {{sfnref}} or {{harvid}}; nil else elseif 'none' == ref then -- |ref=none return nil; -- anchor id expicitly suppressed else anchor_id = ref; -- |ref=<text> may match an anchor id override value in {{harv}} template |ref= parameter end return anchor_id; -- anchor_id text; nil else end --[[--------------------------< A N C H O R _ I D _ M A K E _ C S 1 2 >---------------------------------------- for cs1|2 template and cs1-like templates inspect |ref= to decide what to do: |ref= - empty or missing: get names and date from template parameters; all cs1|2 create CITEREF anchor IDs |ref=harv - get names and date from template parameters |ref={{SfnRef|name|name|name|name|year}} - assemble an anchor id from {{sfnref}} positional parameters |ref={{Harvid|name|name|name|name|year}} - assemble an anchor id from {{harvid}} positional parameters |ref=none - skip; do nothing because an anchor id intentionally suppressed; TODO: keep with a type code of '0'? |ref=<text> - save param value because may match an anchor id override value in {{harv}} template |ref= parameter or {{harvc}} |id= parameter ]] local function anchor_id_make_cs12 (template) local ref; -- content of |ref= local template_name; -- name of the template local anchor_id; -- the assembled anchor id from this template local date; local params = {}; -- table of template parameters template_name = template_name_get (template); -- get first char uppercase trimmed template name; ignore subpages ~/new, ~/sandbox if not template_name or template_skip[template_name] then return nil; -- could not extract template name from (possibly corrupted) template (extraneous opening { in the template will cause this) end if redirects_patent[template_name] then date = date_get (template, alias_patterns_patent_date); -- get date; done here because might be in {{date}} else date = date_get (template, alias_patterns_date); end ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}} because we will strip templates from the cs1|2 template if not ref then if template:match ('|%s*ref%s*=([^|}]+)') then -- |ref={{template}} not found; if there is a |ref= param with an assigned value ref = template:match ('|%s*ref%s*=([^|}]+)'); -- get the value; whitespace is a 'value' if ref then -- nil when |ref=|... or when |ref=}} (no spaces between assignment operator and pipe or closing brace) ref = mw.text.trim (ref); -- something, could be just whitespace, so trim leading / trailing whitespace if '' == ref then -- trimming a string of whitespace makes an empty string ref = nil; -- make empty ref same as missing ref end end end end template_params_get (template, params); -- build a table of template parameters and their values if not ref then -- |ref= not set, might be cite LSA which doesn't support |ref= if 'cite lsa' == template_name then return 'CITEREF' .. (params.last or '') .. (params.year or ''); -- cite LSA always creates an anchor id using only |last= and |year= (no aliases) end end if 'harv' == ref or not ref then -- |ref=harv specified or |ref= missing or empty if redirects_patent[template_name] then -- if this is a cite patent template anchor_id = names_get (params, aliases_inventor); -- inventor names only else -- cs1|2 template anchor_id = names_get (params, aliases_contributor) or -- get contributor, author, or editor names names_get (params, aliases_author) or vnames_get (params, 'vauthors') or -- |vauthors= names_get (params, aliases_editor) or vnames_get (params, 'veditors'); -- |veditors= end if anchor_id then -- if names were gotten anchor_id = 'CITEREF' .. anchor_id .. date; end elseif ref:match ('%b{}') then -- ref holds a template anchor_id = sfnref_get (ref); -- returns content of {{sfnref}} or {{harvid}}; nil else elseif 'none' == ref and not redirects_patent[template_name] then -- |ref=none; not supported by cite patent return nil; -- anchor id expicitly suppressed else anchor_id = ref; -- |ref=<text> may match an anchor id override value in {{harv}} template |ref= parameter end return anchor_id; -- anchor_id text; nil else end --[[--------------------------< L I S T _ A D D >-------------------------------------------------------------- adds an <item> to <list> table; for anchor IDs, the boolean <encode> argument must be set true; no return value ]] local function list_add (item, list, encode) if item then -- if there was an item if encode then -- for anchor IDs ... item = mw.uri.anchorEncode (item); -- encode to remove wikimarkup, convert spaces to underscores etc end if not list[item] then -- if not already saved list[item] = 1; -- save it else -- here when this item already saved list[item] = list[item] + 1; -- to indicate that there are multiple items end end end --[[--------------------------< A N C H O R _ I D _ M A K E _ A N C H O R >------------------------------------ make anchor IDs from {{anchor}}; there may be more than one because {{anchor}} is not limited to the number of anchors it may hold. ]] local function anchor_id_make_anchor (template, anchor_id_list) template = template:gsub ('^{{[^|]+|', ''):gsub ('}}$', '', 1); -- remove outer {{ and }} and template name template = wikilink_strip (template); -- strip any wikilink markup (there shouldn't be any but just in case) local params = {}; local anchor_id; for param in template:gmatch ('%b{}') do -- loop through the template; remove and save templates (presumed to be sfnref or harvid) table.insert (params, param); -- save it template = template:gsub ('%b{}', '', 1); -- remove it from source template end for _, t in ipairs (params) do -- spin through the templates in params anchor_id = sfnref_get (t); -- attempt to decode {{sfnref}} and {{harvid}} if anchor_id then -- nil when not {{sfnref}} or {{harvid}} list_add (anchor_id, anchor_id_list, true); -- add anchor ID to the list end end template = template:gsub ('|%s*|', '|'); -- when pipe follows pipe with or without white space, remove extraneous pipe template = template:gsub ('^|', ''):gsub('|$', ''); -- remove extraneous leading and trailing pipes params = mw.text.split (template, '%s*|%s*'); -- split at the pipe and remove extraneous space characters for _, t in ipairs (params) do -- spin through the anchor IDs anchor_id = mw.text.trim (t); -- trim white space if '' ~= anchor_id then -- should always have something list_add (anchor_id, anchor_id_list, true); -- add anchor ID to the list end end end --[[--------------------------< T E M P L A T E _ L I S T _ A D D >-------------------------------------------- makes a list of templates use in the article. ]] local function template_list_add (template) local template = template:match ('{{%s*(.-)[|}]'); -- keep the case of the template - this is different from template_name_get() if template and not template:match ('^#') then -- found a template or magic word; ignore magic words template=mw.text.trim (template); -- trim whitespace template = Lang_obj:ucfirst (template); -- first character in template name must be uppercase (same as canonical template name) TODO: better way to do this? list_add (template, template_list); -- add to list with (unused) tally end end --[[--------------------------< A N C H O R _ I D _ L I S T _ M A K E >---------------------------------------- makes a list of anchor ids from cs1|2, cs1|2-like, vcite xxx, harvc, anchor, wikicite templates Because cs1|2 wrapper templates can, and often do, hide the author and date parameters inside the wrapper, these parameters are not available in the article's wikisource so {{harv}}, {{sfn}}, and {{harvc}} templates that link correctly to those wrapper templates will incorrectly show error messages. Use |ignore-err=yes in the {{harv}}, {{sfn}}, and {{harvc}} templates to supress the error message. creates a list of templates used in the article for use with the whitelist creates a list of article-local whitelisted anchor IDs from {{sfn whitelist}} ]] local function anchor_id_list_make () article_content_get (); -- attempt to get this article's content if '' == Article_content then -- when there is no article content return ''; -- no point in continuing end local template; -- place to hold the template that we found local template_name; local anchor_id; -- place to hold an anchor id as it is extracted / decoded local find_pattern = '%f[{]{{[^{]'; local tstart, tend = Article_content:find (find_pattern); -- find the first template; do not find template variables: {{{template var|}}} while tstart do template = Article_content:match ('%b{}', tstart); -- get the whole template if not template then break; -- template is nil for some reason (last template missing closing }} for example) so declare ourselves done end template_name = template_name_get (template); -- get first char uppercase trimmed template name; ignore subpages ~/new, ~/sandbox template_list_add (template); -- add this template's name to the list if data.known_templates_cs12 [template_name] then anchor_id = anchor_id_make_cs12 (template); -- extract an anchor id from this template list_add (anchor_id, anchor_id_list, true) elseif data.known_templates_vcite [template_name] then local ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}} because we will strip templates from the vcite template if ref then -- |ref={{template}} anchor_id = sfnref_get (ref); -- returns content of {{sfnref}} or {{harvid}}; nil else list_add (anchor_id, anchor_id_list, true); else local params = {}; template_params_get (template, params); -- build a table of template parameters and their values anchor_id = params['ref']; -- when both set, vcite uses value from |ref= if not anchor_id and params['harvid'] then anchor_id = 'CITEREF' .. params['harvid']; -- in vcite, |harvid= auto-adds 'CITEREF' prefix to the value in |harvid= end list_add (anchor_id, anchor_id_list, true); end elseif data.known_templates_harvc [template_name] then anchor_id = anchor_id_make_harvc (template); -- extract an anchor id from this template list_add (anchor_id, anchor_id_list, true); elseif data.known_templates_wikicite [template_name] then local ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}} if ref then anchor_id = sfnref_get (ref); elseif template:match ('|%s*ref%s*=([^|}]+)') then anchor_id = template:match ('|%s*ref%s*=([^|}]+)'); -- plain-text elseif template:match ('|%s*id%s*=%s*(%b{})') then ref = template:match ('|%s*id%s*=%s*(%b{})'); anchor_id = 'Reference-' .. sfnref_get (ref); elseif template:match ('|%s*id%s*=([^|}]+)') then anchor_id = 'Reference-' .. template:match ('|%s*id%s*=([^|}]+)'); -- plain-text else anchor_id = nil; -- no matches, ensure that anchor_id has no value end if anchor_id then list_add (anchor_id, anchor_id_list, true); end elseif data.known_templates_anchor [template_name] then anchor_id_make_anchor (template, anchor_id_list); -- extract anchor ids from this template if any elseif data.known_templates_sfn_whitelist [template_name] then template = template:gsub ('^{{[^|]+|', ''):gsub ('}}$', '', 1); -- remove outer {{ and }} and template name template = mw.text.trim (template, '%s|'); -- trim leading trailing white space and pipes template = mw.text.split (template, '%s*|%s*'); -- make a table of the template's parameters for _, anchor_id in ipairs (template) do -- spin through this template's parameter if '' ~= anchor_id and not article_whitelist[anchor_id] then anchor_id = mw.uri.anchorEncode (anchor_id) article_whitelist[anchor_id] = 1; -- add to the whitelist end end elseif template_name and whitelist.wrapper_templates[template_name] then anchor_id = anchor_id_make_wrapper (template); -- extract an anchor id from this template if possible list_add (anchor_id, anchor_id_list, true); elseif template_name and template_name:match ('^Cit[ea]') then -- not known, not known wrapper; last gasp, try as cs1-like anchor_id = anchor_id_make_cs12 (template); -- extract an anchor id from this template if possible list_add (anchor_id, anchor_id_list, true); end tstart, tend = Article_content:find (find_pattern, tend); -- search for another template; begin at end of last search end mw.logObject (anchor_id_list, 'anchor_id_list'); mw.logObject (template_list, 'template_list'); mw.logObject (article_whitelist, 'article_whitelist'); return anchor_id_list; end --[[--------------------------< E X P O R T E D _ T A B L E S >------------------------------------------------ ]] return { anchor_id_list = anchor_id_list_make(), -- table of anchor ids available in this article article_whitelist = article_whitelist, -- table of anchor ids with false-positive error message to be suppressed template_list = template_list, -- table of templates used in this article } 9cf1091b65b65bfb32bb0aa2b73bb581d19e99f1 Module:Footnotes/anchor id list/data 828 104 224 223 2022-09-04T15:24:57Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- copied from Module:Ref info/data - maybe overkill here? -- for this application make lists from the redirect lists and force all template names first character uppercase require('Module:No globals'); --[[--------------------------< C S 1 _ T E M P L A T E _ P A T T E R N S >------------------------------------ These are patterns for cs1 templates and their redirects. These patterns exclude redirects that are vcite-like which redirects should be deleted because vcite is not cs1. ]] local cs1_template_patterns = { -- lua patterns of the cannonical names and redirects '[Cc]ite ar[Xx]iv', -- arXiv is the canonical name '[Cc]ite ArXiv', '[Cc]ite AV media', -- canonical '[Cc]ite audio', '[Cc]ite AV', '[Cc]ite AV ?Media', '[Cc]ite av media', '[Cc]ite cd', '[Cc]ite DVD', '[Cc]ite dvd', '[Cc]ite film', '[Cc]ite image', '[Cc]ite media', '[Cc]ite movie', '[Cc]ite music video', '[Cc]ite radio', '[Cc]ite song', '[Cc]ite ?video', '[Cc]ite visual', '[Cc]ite You[Tt]ube', '[Cc]ita vídeo', -- non-English redirect; TODO: tally separately? '[Cc]ite AV media notes', -- canonical '[Cc]ite album[ %-]notes', '[Cc]ite av media notes', '[Cc]ite DVD[ %-]notes', '[Cc]ite dvd%-notes', '[Cc]ite liner notes', '[Cc]ite music release notes', '[Ll]iner notes', '[Cc]ite bio[Rr]xiv', -- bioRxiv is the canonical form '[Cc]ite [Bb]ook', -- book is the canonical form '[Bb]ook cite', '[Bb]ook reference', '[Bb]ook reference url', '[Cc] book', '[Cc]it book', '[Cc]ite books', '[Cc]ite chapter', '[Cc]ite ebook', '[Cc]ite manual', '[Cc]ite page', '[Cc]ite publication', '[Cc]ite score', '[Cc]ite work', '[Cc]ite%-?book', '[Bb]okref', '[Cc]itace monografie', '[Cc]itar livro', -- non-English redirects; TODO: tally separately? '[Cc]iteer boek', '[Oo]uvrage', '[Rr]ef%-llibre', '서적 인용', '[Cc]ite citeseerx', -- canonical '[Cc]ite conference', -- canonical '[Cc]ita conferenza', '[Cc]ite proceedings', '[Cc]onference reference', -- cita conferenza is non-English; TODO: tally separately? '[Cc]ite ?encyclopedia', -- cite encyclopedia is the canonical name '[Cc]ite contribution', '[Cc]ite dic', '[Cc]ite dictionary', '[Cc]ite encyclopaedia', '[Cc]ite encyclopædia', '[Ee]ncyclopedia', '[Cc]ite [Ee]pisode', -- episode is the canonical form '[Cc]ite show', '[Cc]ite interview', -- canonical '[Cc]ite ?journal', -- cite journal is the canonical form '[Cc] journal', '[Cc]itation journal', '[Cc]ite abstract', '[Cc]ite document', '[Cc]ite Journal', '[Cc]ite journal zh', '[Cc]ite ?paper', '[Vv]cite2 journal', '[Cc]ita pubblicazione', '[Cc]itace periodika', '[Cc]itar jornal', -- non-English redirects; TODO: tally separately? '[Cc]itar publicació', '[Cc]ytuj pismo', '[Tt]idskriftsref', 'Навод из стручног часописа', '저널 인용', '[Cc]ite [Mm]agazine', -- magazine is the canonical form '[Cc]ite mag', '[Cc]ite magazine article', '[Cc]ite newsletter', '[Cc]ite periodical', '[Cc]ite mailing ?list', -- mailing list is the canonical form '[Cc]ite list', '[Cc]ite maps?', -- map is the canonical form '[Cc]ite[ %-]?news', -- cite news is the canonical form '[Cc] news', '[Cc]it news', '[Cc]itation news', '[Cc]ite article', '[Cc]ite n', '[Cc]ite new', '[Cc]ite newspaper', '[Cc]ite News', '[Cc]ite news%-q', '[Cc]ite news2', '[Cc]itenewsauthor', '[Cc]ute news', '[Cc]itar notícia', '[Hh]aber kaynağı', '[Tt]idningsref', 'استشهاد بخبر', -- non-English redirects; TODO: tally separately? '뉴스 인용', '[Cc]ite newsgroup', -- canonical '[Cc]ite usenet', '[Cc]ite podcast', -- canonical '[Cc]ite [Pp]ress release', -- press release is the canonical form '[Cc]ite media release', '[Cc]ite news release', '[Cc]ite pr', '[Cc]ite press', '[Cc]ite press release\.', '[Cc]ite press[%-]?release', '[Cc]ite report', -- canonical '[Cc]ite serial', -- canonical '[Cc]ite sign', -- canonical '[Cc]ite plaque', '[Cc]ite speech', -- canonical '[Cc]ite ssrn', -- canonical '[Cc]ite SSRN', '[Cc]ite tech ?report', -- techreport is the canonical form '[Cc]ite standard', '[Cc]ite technical report', '[Tt]echrep reference', '[Cc]ite thesis', -- canonical '[Cc]ite dissertation', '[Cc]itar tese', -- non-English redirect; TODO: tally separately? '[Cc]ite [Ww]eb', -- web is the canonical form '[Cc] web', '[Cc]it web', '[Cc]ite blog', '[Cc]ite URL', '[Cc]ite url', '[Cc]ite w', '[Cc]ite wb', '[Cc]ite we', '[Cc]ite web\.', '[Cc]ite webpage', '[Cc]ite website', '[Cc]ite website article', '[Cc]ite%-?web', '[Cc]itweb', '[Cc]w', '[Rr]ef web', '[Ww]eb citation', '[Ww]eb cite', '[Ww]eb link', '[Ww]eb[ %-]reference', '[Ww]eblink', '[Cc]hú thích web', '[Cc]ita web', '[Cc]itace elektronické monografie', -- non-English redirects; TODO: tally separately? '[Cc]itat web', 'مرجع ويب', 'یادکرد وب', '웹 인용', } --[[--------------------------< C S 2 _ T E M P L A T E _ P A T T E R N S >------------------------------------ These are patterns for cs2 templates redirects. ]] local cs2_template_patterns = { -- lua patterns of the cannonical names and redirects '[Cc]itation', '[Cc]ite', '[Cc]ite citation', '[Cc]ite study', '[Cc]ite [Tt]echnical standard', } --[[--------------------------< V C I T E _ T E M P L A T E _ P A T T E R N S >-------------------------------- These are patterns for Vcite-family templates and their redirects. ]] local vcite_template_patterns = { '[Vv]cite book', -- canonical '[Vv]ancite book', '[Vv]ancite report', '[Vv]cite encyclopedia', '[Vv]cite report', '[Vv]cite journal', -- canonical '[Cc]it journal', '[Cc]it paper', '[Vv]ancite journal', '[Vv]cite paper', '[Vv]cite news', -- canonical '[Vv]ancite news', '[Vv]cite web', -- canonical '[Vv]ancite web', } --[[--------------------------< H A R V C _ T E M P L A T E _ P A T T E R N S >-------------------------------- These are patterns for the harvc template and its redirects. ]] local harvc_template_patterns = { '[Hh]arvc', -- canonical '[Cc]itec', } --[[--------------------------< C S 1 _ L I K E _ T E M P L A T E _ P A T T E R N S >-------------------------- These are patterns for miscellaneous templates and their redirects that 'look like' cs1 templates (begin with cite ...) Because they 'look like' cs1 templates they are handled as if they were cs1 templates. These templates are NOT wrapper templates; names and dates are always to be extracted from the article instantiation of the template. ]] local cs1_like_template_patterns = { '[Cc]ite LSA', -- canonical } --[[--------------------------< W I K I C I T E _ T E M P L A T E _ P A T T E R N S >-------------------------- These are patterns for the wikicite template and its redirects. ]] local wikicite_template_patterns = { '[Ww]ikicite', -- canonical } --[[--------------------------< A N C H O R _ T E M P L A T E _ P A T T E R N S >------------------------------ These are patterns for the anchor template and its redirects. ]] local anchor_template_patterns = { '[Aa]nchors?', -- anchor is canonical form '[Aa]nchor for redirect', '[Aa]nchro', '[Aa]ncor', } --[[--------------------------< S F N _ W H I T E L I S T _ P A T T E R N S >---------------------------------- These are patterns for the anchor template and its redirects. ]] local sfn_whitelist_patterns = { '[Ss]fn whitelist', -- canonical '[Hh]arv whitelist', } --[[--------------------------< K N O W N _ T E M P L A T E S >------------------------------------------------ These tables are created from the *_template_patterns tables. To make these tables, entries in the source tables are evaluated to replace lua patterns with the appropriate characters to create names for the output tables. First charqacter is always uppercase For example: [Cc]ite ar[Xx]iv becomes Cite arXiv Cite arxiv ]] local known_templates_cs12 = {}; -- the exported tables local known_templates_vcite = {}; local known_templates_harvc = {}; local known_templates_wikicite = {}; local known_templates_anchor = {}; local known_templates_sfn_whitelist = {}; local function add_stripped (list, name) if not list[name] then list[name] = true; end end local function pattern_convert (pattern, list) local lead, tail, c, l, name; local first_char_patterns = { '^%[(%a)%a%]', -- leading character (usually uppercase) '^%[%a(%a)%]', -- leading character (usually lowercase) } c = tostring (pattern:match ('%u')); -- tostring() required because I don't know why; lua chokes complaining that c is not a string name = pattern:gsub ('^%[%a%a%]', c); -- replace bracketed first character [Xx] with selected character from the match if name:match ('(.-)%[(%a)(%a)%](.*)') then -- mixed case optional letters lead, c, l, tail = name:match ('(.-)%[(%a)(%a)%](.*)'); add_stripped (list, lead .. c .. tail); -- uppercase add_stripped (list, lead .. l .. tail); -- lowercase elseif name:match ('^([^%[]+)(%[ %%%-%]%?)(.+)$') then -- [ %-]? lead, c, tail = name:match ('^([^%[]+)(%[ %%%-%]%?)(.+)$'); add_stripped (list, lead .. tail); -- neither char add_stripped (list, lead .. ' ' .. tail); -- space add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^([^%[]+)(%[%%%-%]%?)(.+)$') then -- [%-]? lead, c, tail = name:match ('^([^%[]+)(%[%%%-%]%?)(.+)$'); add_stripped (list, lead .. tail); -- no hyphen add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^([^%[]+)(%[ %%%-%])(.+)$') then -- [ %-] lead, c, tail = name:match ('^([^%[]+)(%[ %%%-%])(.+)$'); add_stripped (list, lead .. ' ' .. tail); -- space add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^([^%?]+)(%%%-%?)(.+)$') then -- %-? lead, c, tail = name:match ('^([^%?]+)(%%%-%?)(.+)$'); add_stripped (list, lead .. tail); -- no hyphen add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^(.-)(%%%-)(.+)$') then -- %- lead, c, tail = name:match ('^(.-)(%%%-)(.+)$'); add_stripped (list, lead .. '-' .. tail); -- hyphen elseif name:match ('^(.-)(.)%?(.*)$') then -- .? lead, c, tail = name:match ('^(.-)(.)%?(.*)$'); add_stripped (list, lead .. tail); -- no character add_stripped (list, lead .. c .. tail); -- character else add_stripped (list, name); -- no patterns so save as is end end for _, t in ipairs ({ {cs1_template_patterns, known_templates_cs12}, {cs2_template_patterns, known_templates_cs12}, {cs1_like_template_patterns, known_templates_cs12}, {vcite_template_patterns, known_templates_vcite}, {harvc_template_patterns, known_templates_harvc}, {wikicite_template_patterns, known_templates_wikicite}, {anchor_template_patterns, known_templates_anchor}, {sfn_whitelist_patterns, known_templates_sfn_whitelist}, }) do for _, pattern in ipairs (t[1]) do -- for each patern in *_template_patterns pattern_convert (pattern, t[2]) -- convert and store in known_templates_* end end --[[--------------------------< E X P O R T S >---------------------------------------------------------------- ]] return { known_templates_anchor = known_templates_anchor, known_templates_cs12 = known_templates_cs12, known_templates_harvc = known_templates_harvc, known_templates_vcite = known_templates_vcite, known_templates_wikicite = known_templates_wikicite, known_templates_sfn_whitelist = known_templates_sfn_whitelist, } 6267b1029a020fb98adfa02a74118ae31897ac81 Module:Footnotes/whitelist 828 105 226 225 2022-09-04T15:24:58Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[--------------------------< W R A P P E R _ T E M P L A T E _ D E F A U L T S >---------------------------- A list of wrapper templates by their canonical names – spelling and capitalization is important. Each wrapper template has a table of two values: [1] is the wrapper's default name-list as it is used in an anchor ID; [2] is the default year. This table is indexed indirectly through the wrapper_templates table. This table is not available externally. ]] local wrapper_template_defaults = { -- keys are canonical template names ['Americana'] = {'Rines', '1920'}, -- tables with default name and default year ['Cite EB1911'] = {'Chisholm', '1911'}, -- tables with default name and default year ['EB1911'] = {'Chisholm', '1911'}, ['EI3'] = {'FleetKrämerMatringeNawas', ''}, ['ODNB'] = {'', ''}, -- there is no default anchor ID; this forces evaluation of {{cite ODNB}} redirects } --[[--------------------------< W R A P P E R _ T E M P L A T E _ D E F A U L T S _ V O L >-------------------- For wrapper templates that use |volume= to specify default name (often editor names) and year. Wrapper templates are indexed by their canonical names – spelling and capitalization is important. Each wrapper template has a table of values for every volume. Volumes may be indexed by Arabic or Roman numerals. Each volume index has a table of twp values" [1] is the wrapper's default name-list as it is used in an anchor ID; [2] is the default year. Each wrapper template in this table must have a ['default'] key for those occasions when |volume= is omitted or empty. This table is indexed indirectly through the wrapper_templates table. This table is not available externally. ]] local wrapper_template_defaults_vol = { -- primary keys are canonical template names; TODO: do these keys have to be canonical template names? ['Cite Catholic Encyclopedia'] = { -- secondary keys are volume ['1'] = {'Herbermann', '1907'}, ['2'] = {'Herbermann', '1907'}, ['3'] = {'Herbermann', '1908'}, ['4'] = {'Herbermann', '1908'}, ['5'] = {'Herbermann', '1909'}, ['6'] = {'Herbermann', '1909'}, ['7'] = {'Herbermann', '1910'}, ['8'] = {'Herbermann', '1910'}, ['9'] = {'Herbermann', '1910'}, ['10'] = {'Herbermann', '1911'}, ['11'] = {'Herbermann', '1911'}, ['12'] = {'Herbermann', '1911'}, ['13'] = {'Herbermann', '1912'}, ['14'] = {'Herbermann', '1912'}, ['15'] = {'Herbermann', '1912'}, ['default'] = {'Herbermann', '1913'}, }, ['Cite EB9'] = { ['1'] = {'Baynes', '1878'}, ['I'] = {'Baynes', '1878'}, ['2'] = {'Baynes', '1878'}, ['II'] = {'Baynes', '1878'}, ['3'] = {'Baynes', '1878'}, ['III'] = {'Baynes', '1878'}, ['4'] = {'Baynes', '1878'}, ['IV'] = {'Baynes', '1878'}, ['5'] = {'Baynes', '1878'}, ['V'] = {'Baynes', '1878'}, ['6'] = {'Baynes', '1878'}, ['VI'] = {'Baynes', '1878'}, ['7'] = {'Baynes', '1878'}, ['VII'] = {'Baynes', '1878'}, ['8'] = {'Baynes', '1878'}, ['VIII'] = {'Baynes', '1878'}, ['9'] = {'Baynes', '1879'}, ['IX'] = {'Baynes', '1879'}, ['10'] = {'Baynes', '1879'}, ['X'] = {'Baynes', '1879'}, ['11'] = {'BaynesSmith', '1880'}, ['XI'] = {'BaynesSmith', '1880'}, ['12'] = {'BaynesSmith', '1881'}, ['XII'] = {'BaynesSmith', '1881'}, ['13'] = {'BaynesSmith', '1881'}, ['XIII'] = {'BaynesSmith', '1881'}, ['14'] = {'BaynesSmith', '1882'}, ['XIV'] = {'BaynesSmith', '1882'}, ['15'] = {'BaynesSmith', '1883'}, ['XV'] = {'BaynesSmith', '1883'}, ['16'] = {'BaynesSmith', '1883'}, ['XVI'] = {'BaynesSmith', '1883'}, ['17'] = {'BaynesSmith', '1884'}, ['XVII'] = {'BaynesSmith', '1884'}, ['18'] = {'BaynesSmith', '1885'}, ['XVIII'] = {'BaynesSmith', '1885'}, ['19'] = {'BaynesSmith', '1885'}, ['XIX'] = {'BaynesSmith', '1885'}, ['20'] = {'BaynesSmith', '1886'}, ['XX'] = {'BaynesSmith', '1886'}, ['21'] = {'BaynesSmith', '1886'}, ['XXI'] = {'BaynesSmith', '1886'}, ['22'] = {'BaynesSmith', '1887'}, ['XXII'] = {'BaynesSmith', '1887'}, ['23'] = {'BaynesSmith', '1888'}, ['XXIII'] = {'BaynesSmith', '1888'}, ['24'] = {'BaynesSmith', '1888'}, ['XXIV'] = {'BaynesSmith', '1888'}, ['default'] = {'Baynes', '1875–1889'}, }, ['Encyclopaedia of Islam, New Edition'] = { ['1'] = {'GibbKramersLévi-ProvençalSchacht', '1960'}, ['2'] = {'LewisPellatSchacht', '1965'}, ['3'] = {'LewisMénagePellatSchacht', '1971'}, ['4'] = {'van_DonzelLewisPellatBosworth', '1978'}, ['5'] = {'Bosworthvan_DonzelLewisPellat', '1986'}, ['6'] = {'Bosworthvan_DonzelPellat', '1991'}, ['7'] = {'Bosworthvan_DonzelHeinrichsPellat', '1993'}, ['8'] = {'Bosworthvan_DonzelHeinrichsLecomte', '1995'}, ['9'] = {'Bosworthvan_DonzelHeinrichsLecomte', '1997'}, ['10'] = {'BearmanBianquisBosworthvan_Donzel', '2000'}, ['11'] = {'BearmanBianquisBosworthvan_Donzel', '2002'}, ['12'] = {'BearmanBianquisBosworthvan_Donzel', '2004'}, ['atlas'] = {'Brice', '1981'}, ['abridged'] = {'van_Donzel', '1994'}, ['default'] = {'BearmanBianquisBosworthvan_Donzel', '1960–2005'}, }, ['New Cambridge Medieval History'] = { ['1'] = {'Fouracre', '2005'}, ['2'] = {'McKitterick', '1995'}, ['3'] = {'Reuter', '2000'}, ['4a'] = {'LuscombeRiley-Smith', '2004'}, ['4b'] = {'LuscombeRiley-Smith', '2004'}, ['5'] = {'Abulafia', '1999'}, ['6'] = {'Jones', '2000'}, ['7'] = {'Allmand', '1998'}, ['default'] = {'', '1995–2005'}, }, ['The History of al-Tabari'] = { ['1'] = {'Rosenthal', '1989'}, ['2'] = {'Brinner', '1986'}, ['3'] = {'Brinner', '1991'}, ['4'] = {'Perlmann', '1987'}, ['5'] = {'Bosworth', '1999'}, ['6'] = {'WattMcDonald', '1989'}, ['7'] = {'McDonald', '1987'}, ['8'] = {'Fishbein', '1997'}, ['9'] = {'Poonawala', '1990'}, ['10'] = {'Donner', '1993'}, ['11'] = {'Blankinship', '1993'}, ['12'] = {'Friedmann', '1992'}, ['13'] = {'Juynboll', '1989'}, ['14'] = {'Smith', '1994'}, ['15'] = {'Humphreys', '1990'}, ['16'] = {'Brockett', '1997'}, ['17'] = {'Hawting', '1996'}, ['18'] = {'Morony', '1987'}, ['19'] = {'Howard', '1990'}, ['20'] = {'Hawting', '1989'}, ['21'] = {'Fishbein', '1990'}, ['22'] = {'Rowson', '1989'}, ['23'] = {'Hinds', '1990'}, ['24'] = {'Powers', '1989'}, ['25'] = {'Blankinship', '1989'}, ['26'] = {'Hillenbrand', '1989'}, ['27'] = {'Williams', '1985'}, ['28'] = {'McAuliffe', '1995'}, ['29'] = {'Kennedy', '1990'}, ['30'] = {'Bosworth', '1989'}, ['31'] = {'Fishbein', '1992'}, ['32'] = {'Bosworth', '1987'}, ['33'] = {'Bosworth', '1991'}, ['34'] = {'Kraemer', '1989'}, ['35'] = {'Saliba', '1985'}, ['36'] = {'Waines', '1992'}, ['37'] = {'Fields', '1987'}, ['38'] = {'Rosenthal', '1985'}, ['39'] = {'Landau-Tasseron', '1998'}, ['40'] = {'Popovkin', '2007'}, ['default'] = {'Yarshater', '1985–2007'}, }, } --[[--------------------------< W R A P P E R _ T E M P L A T E S >-------------------------------------------- A list of wrapper templates and their redirects – spelling and capitalization is important; first character is always uppercase. Each wrapper template gets its value from a k/v pair in the wrapper_template_defaults table. article reader queries this table to see if template_name is a wrapper template ]] local wrapper_templates = { -- keys are names of wrapper templates and their redirects ['Americana'] = wrapper_template_defaults['Americana'], -- canonical name; this template calls Cite Americana ['Catholic Encyclopedia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['1913Catholic'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Catholic'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Catholic encyclopedia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['CatholicEncyclopedia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['CE13'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['CE1913'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Cite Americana'] = wrapper_template_defaults['Americana'], -- canonical name ['Cite Catholic Encyclopedia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['CathEncy'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Cite Catholic Encyclopædia'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Cite CE1913'] = wrapper_template_defaults_vol['Cite Catholic Encyclopedia'], ['Cite EB1911'] = wrapper_template_defaults['Cite EB1911'], -- canonical name ['1911EB'] = wrapper_template_defaults['Cite EB1911'], -- redirects ['EB1911 cite'] = wrapper_template_defaults['Cite EB1911'], ['Wikisource1911Enc Citation'] = wrapper_template_defaults['Cite EB1911'], ['Wikisource1911Enc citation'] = wrapper_template_defaults['Cite EB1911'], ['Cite EB9'] = wrapper_template_defaults_vol['Cite EB9'], -- canonical ['Eb9'] = wrapper_template_defaults_vol['Cite EB9'], ['Cite ODNB'] = wrapper_template_defaults['ODNB'], -- canonical ['Cite odnb'] = wrapper_template_defaults['ODNB'], ['DNBweb'] = wrapper_template_defaults['ODNB'], ['OBDNweb'] = wrapper_template_defaults['ODNB'], ['ODNB'] = wrapper_template_defaults['ODNB'], ['ODNBref'] = wrapper_template_defaults['ODNB'], ['ODNBweb'] = wrapper_template_defaults['ODNB'], ['EB1911'] = wrapper_template_defaults['EB1911'], -- canonical name; this template calls Cite EB1911 ['1911'] = wrapper_template_defaults['EB1911'], -- redirects ['1911s'] = wrapper_template_defaults['EB1911'], ['Britannica 1911'] = wrapper_template_defaults['EB1911'], ['Encyclopedia Britannica 1911'] = wrapper_template_defaults['EB1911'], ['Encyclopædia Britannica 1911'] = wrapper_template_defaults['EB1911'], ['EB9'] = wrapper_template_defaults_vol['Cite EB9'], -- canonical; this template calls Cite EB9 ['Encyclopaedia of Islam, New Edition'] = wrapper_template_defaults_vol['Encyclopaedia of Islam, New Edition'], -- canonical ['EI2'] = wrapper_template_defaults_vol['Encyclopaedia of Islam, New Edition'], ['Encyclopaedia of Islam, THREE'] = wrapper_template_defaults['EI3'], -- canonical ['EI3'] = wrapper_template_defaults['EI3'], ['New Cambridge Medieval History'] = wrapper_template_defaults_vol['New Cambridge Medieval History'], -- canonical ['The History of al-Tabari'] = wrapper_template_defaults_vol['The History of al-Tabari'], -- canonical ['The History of Al-Tabari'] = wrapper_template_defaults_vol['The History of al-Tabari'], -- redirects ['The History of al-Ṭabarī'] = wrapper_template_defaults_vol['The History of al-Tabari'], -- redirects } --[[--------------------------< T E M P L A T E _ N A M E S >-------------------------------------------------- This table holds the names of templates and the names of their redirects. Template names must be written exactly as they are named at their templatespace page. This same also applies to redirects. The indexes in this table are not critical but should be short and concise. ]] local template_names = { ['ADB'] = {'Allgemeine Deutsche Biographie', 'Cite ADB'}, ['Butt_Stations'] = {'Butt-Stations', 'Butt-stations'}, ['Cam_Hist_Iran'] = {'Cambridge History of Iran', 'The Cambridge History of Iran'}, ['DNB'] = {'Cite DNB', 'DNB', 'DNB Cite', 'Cite DNBSupp', 'DNBSupp', 'Cite DNB12', 'Cite DNBIE', 'DNB12', 'DNBIE', 'DNBfirst'}, ['ME-ref'] = {'ME-ref', 'Me-ref'}, ['ODB'] = {'ODB', 'Oxford Dictionary of Byzantium'}, ['ODLA'] = {'ODLA', 'Oxford Dictionary of Late Antiquity'}, ['NDB'] = {'Cite NDB', 'NDB'}, ['Iranica'] = {'Encyclopædia Iranica Online', 'Encyclopædia Iranica', 'Encyclopaedia Iranica', 'Cite Encyclopædia Iranica Online'}, } --[[--------------------------< S P E C I A L _ P A T T E R N S >---------------------------------------------- Lua patterns. These are scanned sequentially which costs time and processing far and above the time and processing needed to index into whitelist{}. Do not create a pattern here if a normal whitelist entry or entries can be created. ]] local special_patterns = { 'CITEREFACAD%u%u%u?%u?%d+%u%u?', -- {{Acad}} ID appears to be 2-4 letters, then 3 numbers, then 1-2 letters 'CITEREFAHD%d+', -- {{Cite AHD}} 'CITEREFHistoric_England%d+', -- {{National Heritage List for England}} & {{PastScape}} 'CITEREFHistoric_Environment_Scotland%u%u%u?%u?%d', -- {{Historic Environment Scotland}} %u can be BTL, GLD, HMPA, LB, SM 'CITEREFQHR%d+', -- {{Cite QHR}} 'CITEREF[%d%a_%pöüäß→]+_at_Bach_Digital', -- {{BDh}} 'CITEREF[BR]GBl_[12]%d%d%d%-?I?I?%/%d+', -- {{Cite Austrian gazette}} 'CITEREFStGBl_[12]%d%d%d%/%d+', -- {{Cite Austrian gazette}} 'CITEREFGBlÖ_[12]%d%d%d%/%d+', -- {{Cite Austrian gazette}} } --[[--------------------------< D N B _ S P E C I A L _ P A T T E R N S >-------------------------------------- Lua patterns. Note at special_patterns applies. These for the DNB templates only; these will be tried only when there is a DNB template in the article. Pretty much any author name during the period 1885–1901 inclusive, and 1912. The DNBIE was published in 1903, and Template:DNBIE says that its use is deprecated, but we do not fight that battle here. ]] local DNB_special_patterns = { 'CITEREF%a[%a%-_\']*188[5-9]', -- 1885–1889 'CITEREF%a[%a%-_\']*189%d', -- 1890–1899 'CITEREF%a[%a%-_\']*190[0-1]', -- 1900–1901 'CITEREF%a[%a%-_\']*1903', -- 1903 IE 'CITEREF%a[%a%-_\']*1912', -- 1912 supplement } --[[--------------------------< W H I T E L I S T >------------------------------------------------------------ This is a list of anchor IDs known to be associated with specific wrapper templates. The anchor ID serves as an index into the table. The assigned value is another table that lists the associated template and any redirects. Except for year disambiguators, anchor IDs must have the same form as the anchor creator makes; must be the anchor-encoded form. Remove the year disambiguator. Template names must be written exactly as they are named at their templatespace page. This same also applies to redirects. Module:Footnotes reads the template names left to right so most-commonly-used template or redirect name should appear first. When there are more than one name and when those templates have various anchor IDs the template namelist should be added to the template_names{} table. Note that references to Template:EB1911 are listed under "E" in the alphabetical list below to keep them organized. ]] local whitelist = { ----------< # >---------- ['CITEREF2013_Statistical_Yearbook_of_the_Republic_of_Croatia'] = {'Croatia Yearbook 2013'}, ----------< A >---------- ['CITEREFAGA_1884–1897'] = {'Schubert\'s compositions (references)'}, ['CITEREFATOC2009'] = {'ATOCConnectingCommunitiesReportS10'}, ['CITEREFAbaevBailey1985'] = template_names['Iranica'], ['CITEREFAbbas1988'] = template_names['Iranica'], ['CITEREFAbbas1989'] = template_names['Iranica'], ['CITEREFAbramowitzStegun1983'] = {'Abramowitz Stegun ref'}, ['CITEREFActa_Lipsiensium1723'] = {'Bach\'s compositions (sources)'}, ['CITEREFAdamsFranzosa2009'] = {'Adams Franzosa Introduction to Topology Pure and Applied'}, ['CITEREFAdaschErnstKeim1978'] = {'Adasch Topological Vector Spaces'}, ['CITEREFAffleck1978'] = {'Affleck-On Track'}, ['CITEREFAhlgrimm1969'] = {'Bach\'s compositions (sources)'}, ['CITEREFAhmadiNegahban2013'] = {'Encyclopaedia Islamica'}, ['CITEREFAhrons1927'] = {'Book-Ahrons-British Steam Railway Locomotive'}, ['CITEREFAl-Kindi1912'] = {'The Governors and Judges of Egypt'}, ['CITEREFAlbert_Schumann1886'] = {'Cite ADB'}, ['CITEREFAlden1916'] = {'Shakespeare sonnets bibliography'}, ['CITEREFAldrich1969'] = {'Aldrich-LocosGER7'}, ['CITEREFAleksidze2018'] = template_names['ODLA'], ['CITEREFAlexiou2010'] = {'Cite flatiron'}, ['CITEREFAlgar1983'] = template_names['Iranica'], ['CITEREFAlgar1989'] = template_names['Iranica'], ['CITEREFAlgar1990'] = template_names['Iranica'], ['CITEREFAlgar2003'] = template_names['Iranica'], ['CITEREFAlizadeh1990'] = template_names['Iranica'], ['CITEREFAllamaniPanagiotopoulou1978'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFAllcockDaviesle_FlemingMaskelyne1968'] = {'RCTS-LocosGWR-1'}, ['CITEREFAllenBoddyBrownFry1970'] = {'RCTS-LocosLNER-8A'}, ['CITEREFAllenBoddyBrownFry1971'] = {'RCTS-LocosLNER-8B'}, ['CITEREFAllenBoddyBrownFry1983'] = {'RCTS-LocosLNER-8A'}, ['CITEREFAmanat1998'] = template_names['Iranica'], ['CITEREFAmanat1999'] = template_names['Iranica'], ['CITEREFAmbartsumian2014'] = template_names['Iranica'], ['CITEREFAmerican_Railway_Association1922'] = {'1922 Locomotive Cyclopedia'}, ['CITEREFAnderson1952'] = {'Naval Wars in the Levant 1559–1853'}, ['CITEREFAndo2000'] = template_names['Iranica'], ['CITEREFAngelov2018'] = template_names['ODLA'], ['CITEREFAnwārEIr1985'] = template_names['Iranica'], ['CITEREFArkhangel&#039;skiiPonomarev1984'] = {'Arkhangel\'skii Ponomarev Fundamentals of General Topology Problems and Exercises'}, ['CITEREFArrey_von_Dommer1875'] = {'Cite ADB'}, ['CITEREFAshraf2006'] = template_names['Iranica'], ['CITEREFAslanianBerberian2009'] = template_names['Iranica'], ['CITEREFAsmus1966'] = template_names['NDB'], ['CITEREFAsmussen1985'] = template_names['Iranica'], ['CITEREFAspreas1929'] = {'Great Military and Naval Encyclopaedia'}, ['CITEREFAtkins2007'] = {'Shakespeare sonnets bibliography'}, ['CITEREFAube2011'] = template_names['Iranica'], ['CITEREFAudiKondevWangHuang2017'] = {'NUBASE2016'}, ['CITEREFAvdoyan2018'] = template_names['ODLA'], ['CITEREFAwdry1990'] = {'Awdry-RailCo', 'Carnarvonshire Railway'}, ['CITEREFAzarnoosh2021'] = template_names['Iranica'], ['CITEREFRamelli2018'] = {'Oxford Dictionary of Late Antiquity'},['CITEREFA_History_of_the_Crusades'] = {'Setton-A History of the Crusades'}, ----------< B >---------- ['CITEREFBabinger1962'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFBabinger1978'] = {'Mehmed the Conqueror and His Time'}, ['CITEREFBabinger1992'] = {'Mehmed the Conqueror and His Time'}, ['CITEREFBachAgricola1754'] = {'Bach\'s compositions (sources)'}, ['CITEREFBadura-SkodaBranscombe2008'] = {'Schubert\'s compositions (references)'}, ['CITEREFBahramianHirtensteinGholami2013'] = {'Encyclopaedia Islamica'}, ['CITEREFBalcer1990'] = template_names['Iranica'], ['CITEREFBaldwin1969'] = {'Setton-A History of the Crusades'}, ['CITEREFBaldwin1985'] = {'Setton-A History of the Crusades'}, ['CITEREFBaldwinKazhdan1991'] = template_names['ODB'], ['CITEREFBaldwinTalbot1991'] = template_names['ODB'], ['CITEREFBaltzer1916'] = {'Baltzer-Kolonialbahnen'}, ['CITEREFBanach1932'] = {'Banach Théorie des Opérations Linéaires'}, ['CITEREFBandy2021'] = template_names['Iranica'], ['CITEREFBartusis1991'] = template_names['ODB'], ['CITEREFBaxter1971'] = {'Baxter-BritishLocoCat1'}, ['CITEREFBaxter1977'] = {'Baxter-BritishLocoCat1'}, ['CITEREFBaxter1978'] = {'Baxter-BritishLocoCat2A'}, ['CITEREFBaxter1979'] = {'Baxter-BritishLocoCat2B'}, ['CITEREFBaxter1982'] = {'Baxter-BritishLocoCat3A', 'Baxter-BritishLocoCat3B'}, ['CITEREFBaxter1984'] = {'Baxter-BritishLocoCat4'}, ['CITEREFBaxter1986'] = {'Baxter-BritishLocoCat5A'}, ['CITEREFBaxter1988'] = {'Baxter-BritishLocoCat5B'}, ['CITEREFBaxter2012'] = {'Baxter-BritishLocoCat6'}, ['CITEREFBeattie1986'] = template_names['Iranica'], ['CITEREFBeißwenger1991'] = {'Bach\'s compositions (sources)'}, ['CITEREFBek2001'] = {'Cite Grove'}, ['CITEREFBelke1996'] = {'Tabula Imperii Byzantini'}, ['CITEREFBelkeMersisch1990'] = {'Tabula Imperii Byzantini'}, ['CITEREFBelkeRestle1984'] = {'Tabula Imperii Byzantini'}, ['CITEREFBellini2008'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFBernardini2003'] = template_names['Iranica'], ['CITEREFBernhard_von_Poten1889'] = template_names['ADB'], ['CITEREFBernhard_von_Poten1898'] = template_names['ADB'], ['CITEREFBernjian2008'] = {'Encyclopaedia Islamica'}, ['CITEREFBezilla1980'] = {'Bezilla-PRR-Electric-Traction'}, ['CITEREFBianquis1998'] = {'The Cambridge History of Egypt', 'Cambridge History of Egypt'}, ['CITEREFBickerman1983'] = template_names['Cam_Hist_Iran'], ['CITEREFBierstedt1988'] = {'Bierstedt An Introduction to Locally Convex Inductive Limits'}, ['CITEREFBiran2009'] = template_names['Iranica'], ['CITEREFBirken1976'] = {'Die Provinzen des Osmanischen Reiches'}, ['CITEREFBivar1983'] = template_names['Cam_Hist_Iran'], ['CITEREFBivar2003'] = template_names['Iranica'], ['CITEREFBlair2002'] = template_names['Iranica'], ['CITEREFBlair2021'] = template_names['Iranica'], ['CITEREFBlake1966'] = {'DisraeliRef'}, ['CITEREFBlanken2019'] = {'Bach\'s compositions (sources)'}, ['CITEREFBlankinship1994'] = {'The End of the Jihâd State', 'The End of the Jihad State'}, ['CITEREFBlautSchulze2008'] = {'Bach\'s compositions (sources)'}, ['CITEREFBloom2007'] = {'Cite Routledge Broadway', 'Cite Broadway Routledge', 'Cite Routledge Guide to Broadway', 'Routledge Guide to Broadway'}, ['CITEREFBock1978'] = {'Audie-bock-directors'}, ['CITEREFBoddyBrownFryHennigan1968'] = {'RCTS-LocosLNER-4'}, ['CITEREFBoddyBrownFryHennigan1975'] = {'RCTS-LocosLNER-2B'}, ['CITEREFBoddyBrownFryHennigan1977'] = {'RCTS-LocosLNER-9A', 'RCTS-LocosLNER-9B'}, ['CITEREFBoddyBrownFryHennigan1979'] = {'RCTS-LocosLNER-3A'}, ['CITEREFBoddyBrownHenniganHoole1984'] = {'RCTS-LocosLNER-6C'}, ['CITEREFBoddyBrownHenniganNeve1981'] = {'RCTS-LocosLNER-3B'}, ['CITEREFBoddyBrownNeveYeadon1983'] = {'RCTS-LocosLNER-6B'}, ['CITEREFBoddyFryHenniganHoole1990'] = {'RCTS-LocosLNER-10B'}, ['CITEREFBoddyFryHenniganProud1963'] = {'RCTS-LocosLNER-1'}, ['CITEREFBoddyNeveTeeYeadon1982'] = {'RCTS-LocosLNER-6A'}, ['CITEREFBoddyNeveYeadon1973'] = {'RCTS-LocosLNER-2A'}, ['CITEREFBody1989'] = {'Body-Railways-Vol2'}, ['CITEREFBon1969'] = {'La Morée franque'}, ['CITEREFBonebakker1997'] = template_names['Iranica'], ['CITEREFBonner2010'] = {'New Cambridge History of Islam'}, ['CITEREFBonnett2005'] = {'Bonnett Practical Rail Engineering'}, ['CITEREFBonporti1712'] = {'Bach\'s compositions (sources)'}, ['CITEREFBooth2000'] = {'Shakespeare sonnets bibliography'}, ['CITEREFBorsari1964'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFBossert1914'] = {'Schaff-Herzog'}, ['CITEREFBosworth1968'] = template_names['Cam_Hist_Iran'], ['CITEREFBosworth1975'] = template_names['Cam_Hist_Iran'], ['CITEREFBosworth1983'] = template_names['Iranica'], ['CITEREFBosworth1984'] = template_names['Iranica'], ['CITEREFBosworth1987'] = template_names['Iranica'], ['CITEREFBosworth1988'] = template_names['Iranica'], ['CITEREFBosworth1989'] = template_names['Iranica'], ['CITEREFBosworth1994'] = template_names['Iranica'], ['CITEREFBosworth1995'] = template_names['Iranica'], ['CITEREFBosworth1997'] = template_names['Iranica'], ['CITEREFBosworth1998'] = template_names['Iranica'], ['CITEREFBosworth2000'] = template_names['Iranica'], ['CITEREFBosworth2001'] = template_names['Iranica'], ['CITEREFBosworth2002'] = template_names['Iranica'], ['CITEREFBosworth2003'] = template_names['Iranica'], ['CITEREFBosworth2008'] = template_names['Iranica'], ['CITEREFBosworth2009'] = template_names['Iranica'], ['CITEREFBosworth2010'] = template_names['Iranica'], ['CITEREFBosworth2011'] = template_names['Iranica'], ['CITEREFBosworthCrane1984'] = template_names['Iranica'], ['CITEREFBottoMitchell2002'] = {'Cite ATT Broadway', 'Cite At This Theatre Broadway', 'Cite Broadway At This Theatre', 'Cite Broadway ATT'}, ['CITEREFBourbaki1987'] = {'Bourbaki Topological Vector Spaces'}, ['CITEREFBourbaki1989'] = {'Bourbaki General Topology Part I Chapters 1-4', 'Bourbaki General Topology Part II Chapters 5-10', 'Bourbaki Algebra I Chapters 1-3 Springer'}, ['CITEREFBourbaki1994'] = {'Bourbaki EHM'}, ['CITEREFBowen1928'] = {'The Life and Times of Ali ibn Isa'}, ['CITEREFBowmanCameronGarnsey2005'] = {'Cambridge Ancient History'}, ['CITEREFBoyce1983'] = template_names['Iranica'], ['CITEREFBoyce1986'] = template_names['Iranica'], ['CITEREFBoyce1989'] = template_names['Iranica'], ['CITEREFBoyce2000'] = template_names['Iranica'], ['CITEREFBoyce2009'] = template_names['Iranica'], ['CITEREFBoyd1970'] = {'Boyd-MidWales'}, ['CITEREFBoyd1975'] = {'Boyd-FR1'}, ['CITEREFBoyd1985'] = {'Boyd-NCaerns2Penrhyn'}, ['CITEREFBoyd1986'] = {'Boyd-NCaerns3Dinorwic'}, ['CITEREFBoyd1988'] = {'Boyd-SCaerns1'}, ['CITEREFBoyd1989'] = {'Boyd-SCaerns2'}, ['CITEREFBoyd1990'] = {'Boyd-NCaerns1'}, ['CITEREFBradshaw1968'] = {'Bradshaw-1910April'}, ['CITEREFBradshaw1985'] = {'Bradshaw-1922July'}, ['CITEREFBradshaw2011'] = {'Bradshaw-1895December'}, ['CITEREFBradshaw2012'] = {'Bradshaw-1850March'}, ['CITEREFBrand1968'] = {'Byzantium Confronts the West'}, ['CITEREFBrand1991'] = {'DBI', 'ODB', 'Oxford Dictionary of Byzantium'}, ['CITEREFBray2010'] = {'Bray-SDJR'}, ['CITEREFBrett2010'] = {'New Cambridge History of Islam'}, ['CITEREFBriant1985'] = template_names['Iranica'], ['CITEREFBrosius2000'] = template_names['Iranica'], ['CITEREFBrown2000'] = template_names['Iranica'], ['CITEREFBrown2008'] = {'The Cambridge History of the Byzantine Empire'}, ['CITEREFBrunner1975'] = template_names['Cam_Hist_Iran'], ['CITEREFBrunner1983'] = template_names['Cam_Hist_Iran'], ['CITEREFBrunner1984'] = template_names['Iranica'], ['CITEREFBrunner1986'] = template_names['Iranica'], ['CITEREFBryan1886'] = {'Bryan (3rd edition)'}, ['CITEREFBryan1889'] = {'Bryan (3rd edition)'}, ['CITEREFBuhle1909'] = {'Bach\'s compositions (sources)'}, ['CITEREFBulliet1984'] = template_names['Iranica'], ['CITEREFBulookbashiNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFBunbury1857'] = {'DGRG'}, ['CITEREFBurant1987'] = {'Cite DCB'}, ['CITEREFBurch1911'] = {'Burch Electric Traction'}, ['CITEREFBurke1866'] = {'O\'Donnell family tree'}, ['CITEREFBurn1985'] = template_names['Cam_Hist_Iran'], ['CITEREFBurrowsWallace1999'] = {'Cite gotham'}, ['CITEREFBury1911'] = {'The Imperial Administrative System of the Ninth Century'}, ['CITEREFBusse1975'] = template_names['Cam_Hist_Iran'], ['CITEREFBusse1982'] = template_names['Iranica'], ['CITEREFButcherNicholson2018'] = template_names['ODLA'], ['CITEREFButt1995'] = template_names['Butt_Stations'], ['CITEREFBöwering1995'] = template_names['Iranica'], ['CITEREFBürgelMottahedeh1988'] = template_names['Iranica'], ----------< C >---------- ['CITEREFCIC1983'] = {'CIC1983bib'}, ['CITEREFCalifornia1988'] = {'CA-Rail Passenger Development Plan-1988'}, ['CITEREFCalmard1988'] = template_names['Iranica'], ['CITEREFCalmard1999'] = template_names['Iranica'], ['CITEREFCaltrans1984'] = {'Countrystudy'}, ['CITEREFCameronWard-PerkinsWhitby2000'] = {'Cambridge Ancient History'}, ['CITEREFCanepa2018'] = template_names['ODLA'], ['CITEREFCanny2008'] = {'O\'Donnell family tree'}, ['CITEREFCappelCutlerKazhdan1991'] = template_names['ODB'], ['CITEREFCarl_von_Prantl1879'] = {'Cite ADB'}, ['CITEREFCarlson2010'] = {'Dlmf'}, ['CITEREFCaro1974'] = {'Cite Power Broker'}, ['CITEREFCarpenter1977'] = template_names['ME-ref'], ['CITEREFCarpenter1981'] = template_names['ME-ref'], ['CITEREFCarra_de_VauxHodgson1965'] = {'EI2'}, ['CITEREFCarter2006'] = {'Carter-RailwaysMotivePowerArgentina'}, ['CITEREFCasserley1968'] = {'Casserley-joint'}, ['CITEREFCasserleyJohnston1966'] = {'Casserley-LocoGrouping3'}, ['CITEREFCasserleyJohnston1974'] = {'Casserley-LocoGrouping3', 'Casserley-LocoGrouping2', '0-7110-0554-0'}, ['CITEREFCasway1984'] = {'O\'Donnell family tree'}, ['CITEREFCavanna_Ciappina2001'] = {'DBI'}, ['CITEREFCawley2001'] = {'Medieval Lands by Charles Cawley', 'MLCC'}, ['CITEREFCawley2001'] = {'Medieval Lands by Charles Cawley'}, ['CITEREFCawley2010'] = {'MLCC'}, ['CITEREFCawley2011'] = {'MLCC'}, ['CITEREFChaléardChanson-JabeurBéranger2006'] = {'Chaléard-Le cdf en Afrique'}, ['CITEREFChambers1728'] = {'Cyclopaedia 1728'}, ['CITEREFChasiotis1975'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFChaumont1985'] = template_names['Iranica'], ['CITEREFChaumont1986'] = template_names['Iranica'], ['CITEREFChaumont1987'] = template_names['Iranica'], ['CITEREFChaumont1990'] = template_names['Iranica'], ['CITEREFChaumontSchippmann1988'] = template_names['Iranica'], ['CITEREFCheyneBlack1899'] = {'Biblica', 'Cite Biblica'}, ['CITEREFCheyneBlack1899–1903'] = {'Cite Biblica'}, ['CITEREFCheyneBlack1901'] = {'Cite Biblica'}, ['CITEREFCheyneBlack1902'] = {'Cite Biblica'}, ['CITEREFCheyneBlack1903'] = {'Cite Biblica'}, ['CITEREFChisholm1922'] = {'EB1922', 'Cite EB1922'}, ['CITEREFChittick1997'] = template_names['Iranica'], ['CITEREFChkeidze2001'] = template_names['Iranica'], ['CITEREFChoniates1984'] = {'O City of Byzantium'}, ['CITEREFChrista_Jost1999'] = template_names['NDB'], ['CITEREFChung1994'] = {'Country study'}, ['CITEREFChurchmanHurst2001'] = {'Churchman & Hurst Railways of New Zealand'}, ['CITEREFChurchman_&amp;_Hurst2001'] = {'Churchman & Hurst Railways of New Zealand'}, ['CITEREFChurella2013'] = {'Churella-PRR-1'}, ['CITEREFClementsMcMahon2008'] = {'ClementsMcMahon-GSR Locomotives'}, ['CITEREFClinker1978'] = {'Clinker-Stations'}, ['CITEREFClinker1988'] = {'Clinker-Stations'}, ['CITEREFCoates1990'] = {'Coates-Reading'}, ['CITEREFColbyWilliams1916'] = {'New International Encyclopedia', 'NIE'}, ['CITEREFColledgeWarlow2006'] = {'Colledge', 'Cite Colledge2006'}, ['CITEREFColledgeWarlow2010'] = {'Cite Colledge2010'}, ['CITEREFCollins2016'] = {'Cite Collins 2016'}, ['CITEREFConolly1998'] = {'IanAllan-PreGroup-Atlas1998'}, ['CITEREFConway1990'] = {'Conway A Course in Functional Analysis'}, ['CITEREFCosentino2008'] = {'DBI'}, ['CITEREFCoulthard-Clark2002'] = {'Australian Dictionary of Biography'}, ['CITEREFCousin1910'] = {'A Short Biographical Dictionary of English Literature', 'Cite SBDEL'}, ['CITEREFCox1967'] = {'Cox-Upper Darby'}, ['CITEREFCox2011'] = {'Cox-Dixie'}, ['CITEREFCrevier1993'] = {'Crevier 1993'}, ['CITEREFCrockett2007'] = {'Australian Dictionary of Biography'}, ['CITEREFCroke2018'] = template_names['ODLA'], ['CITEREFCrone1980'] = {'Slaves on Horses'}, ['CITEREFCronin2011'] = template_names['Iranica'], ['CITEREFCroughtonKidnerYoung1982'] = {'Croughton-PrivateStations'}, ['CITEREFCruickshanks1970'] = {'HistoryofParliament'}, ['CITEREFCudahy2002'] = {'Cudahy-Hudson'}, ['CITEREFCudahy2003'] = {'Cudahy-Subways'}, ['CITEREFCurta2006'] = {'Southeastern Europe in the Middle Ages, 500–1250'}, ----------< D >---------- ['CITEREFDBI'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFDZS2015'] = {'Croatia Yearbook 2015'}, ['CITEREFDadelsen1957'] = {'Bach\'s compositions (sources)'}, ['CITEREFDaftary1990'] = {'Daftary-The Ismailis'}, ['CITEREFDaftary2003'] = template_names['Iranica'], ['CITEREFDaftary2007'] = {'Daftary-The Ismailis'}, ['CITEREFDaftary2015'] = template_names['Iranica'], ['CITEREFDaiber1988'] = template_names['Iranica'], ['CITEREFDandamayevShahbaziLecoq1986'] = template_names['Iranica'], ['CITEREFDaniel2000'] = template_names['Iranica'], ['CITEREFDaniel2010'] = {'New Cambridge History of Islam'}, ['CITEREFDanielsDench1963'] = {'Daniels-NoMore'}, ['CITEREFDanielsDench1973'] = {'Daniels-NoMore'}, ['CITEREFDanner1975'] = template_names['Cam_Hist_Iran'], ['CITEREFDarleyCanepa2018'] = {'Oxford Dictionary of Late Antiquity'}, ['CITEREFDaryaee2009'] = template_names['Iranica'], ['CITEREFDaryaee2018'] = template_names['ODLA'], ['CITEREFDaryaeeCanepa2018'] = template_names['ODLA'], ['CITEREFDavid1961'] = {'Bach\'s compositions (sources)'}, ['CITEREFDavidson2010'] = {'HistoryofParliament'}, ['CITEREFDavidsonThrush2010'] = {'HistoryofParliament'}, ['CITEREFDavies1996'] = {'Davies-PLMLocoList'}, ['CITEREFDavies1997'] = {'Davies-NordLocoList'}, ['CITEREFDavies2001'] = {'Davies-EstLocoList3', 'Davies-ÉtatLocoList'}, ['CITEREFDavies2003'] = {'Davies-SNCFLocoList'}, ['CITEREFDaviesFirthLuckingThomas1966'] = {'RCTS-LocosGWR-10'}, ['CITEREFDavud2018'] = {'Encyclopaedia Islamica'}, ['CITEREFDavudNazerian2008'] = {'Encyclopaedia Islamica'}, ['CITEREFDe_Negri1997'] = {'DBI'}, ['CITEREFDemircan2010'] = {'TDV Encyclopedia of Islam'}, ['CITEREFDeutsch1951'] = {'Schubert\'s compositions (references)'}, ['CITEREFDeutsch1978'] = {'Schubert\'s compositions (references)'}, ['CITEREFDeutsche_Autos,_Band_2,2001'] = {'Deutsche Autos-2'}, ['CITEREFDeutsche_Autos,_Band_3,2001'] = {'Deutsche Autos-3'}, ['CITEREFDeutsche_Autos,_Band_4,2001'] = {'Deutsche Autos-4'}, ['CITEREFDeutsche_Autos,_Band_5,2001'] = {'Deutsche Autos-5'}, ['CITEREFDeutsche_Autos,_Band_6,2001'] = {'Deutsche Autos-6'}, ['CITEREFDewick2005'] = {'Dewick-Atlas'}, ['CITEREFDiamonstein-Spielvogel2011'] = {'Cite landmarks'}, ['CITEREFDickens2018'] = template_names['ODLA'], ['CITEREFDirksen1998'] = {'Bach\'s compositions (sources)'}, ['CITEREFDirksen2010'] = {'Bach\'s compositions (sources)'}, ['CITEREFDirksen2016'] = {'Bach\'s compositions (sources)'}, ['CITEREFDixmier1984'] = {'Dixmier General Topology'}, ['CITEREFDoerfer1989'] = template_names['Iranica'], ['CITEREFDoganis1930'] = {'Great Military and Naval Encyclopaedia'}, ['CITEREFDoleckiMynard2016'] = {'Dolecki Mynard Convergence Foundations Of Topology'}, ['CITEREFDolkart1998'] = {'Cite morningside'}, ['CITEREFDonner1995'] = template_names['Iranica'], ['CITEREFDonohue2003'] = {'The Buwayhid Dynasty in Iraq'}, ['CITEREFDorin1972'] = {'Dorin-North Western'}, ['CITEREFDow1962'] = {'Dow-GC2'}, ['CITEREFDow1965'] = {'Dow-GC3'}, ['CITEREFDow1985'] = {'Dow-GC1'}, ['CITEREFDowney2007'] = {'Downey-Chicago'}, ['CITEREFDrechsler2005'] = template_names['Iranica'], ['CITEREFDrummond1964'] = {'HistoryofParliament'}, ['CITEREFDrury1985'] = {'Drury Historical Guide 1985'}, ['CITEREFDrury1993'] = {'Drury-North American Steam'}, ['CITEREFDuchesne-Guillemin1994'] = template_names['Iranica'], ['CITEREFDugundji1966'] = {'Dugundji Topology'}, ['CITEREFDuke1995'] = {'Duke-Santa Fe-1'}, ['CITEREFDukeKeilty1990'] = {'Duke-RDC'}, ['CITEREFDumbarton_Oaks_Hagiography_Database'] = {'Dumbarton Oaks Hagiography Database'}, ['CITEREFDunbar1969'] = {'Dunbar-Railroads'}, ['CITEREFDuncan-Jones2010'] = {'Shakespeare sonnets bibliography'}, ['CITEREFDunlop1895'] = {'O\'Donnell family tree'}, ['CITEREFDunlop1985'] = template_names['Iranica'], ['CITEREFDunn2013'] = {'Dunn-Comeng-5'}, ['CITEREFDurand-Guédy2008'] = template_names['Iranica'], ['CITEREFDurand-Guédy2010'] = template_names['Iranica'], ['CITEREFDurand-Guédy2013'] = {'Encyclopaedia Islamica'}, ['CITEREFDurham1998'] = {'California\'s Geographic Names'}, ['CITEREFDurrant1972'] = {'Durrant-Steam Locos Eastern Europe'}, ['CITEREFDurrant1981'] = {'Durrant-Garratt-Rev'}, ['CITEREFDurrantLewisJorgensen1981'] = {'Durrant-SteamAfrica'}, ['CITEREFDömlingKohlhase1971'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürr1952'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürr1954'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürr1987'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürrJones2006'] = {'Bach\'s compositions (sources)'}, ['CITEREFDürrKobayashi1998'] = {'Bach\'s compositions (sources)'}, ['CITEREFde_Blois2000'] = template_names['Iranica'], ['CITEREFde_Planhol1987'] = template_names['Iranica'], ['CITEREFde_Planhol1988'] = template_names['Iranica'], ----------< E >---------- ['CITEREFEIr.1994'] = template_names['Iranica'], ['CITEREFEarle2018'] = {'Gymnosperm Database'}, ['CITEREFEbata2019'] = {'BDh'}, ['CITEREFEbata2020'] = {'BDh'}, ['CITEREFEbrahimKhodaverdian2018'] = {'Encyclopaedia Islamica'}, ['CITEREFEdwards1995'] = {'Edwards Functional Analysis Theory and Applications'}, ['CITEREFEichberg1976'] = {'Bach\'s compositions (sources)'}, ['CITEREFEilers1983'] = template_names ['Cam_Hist_Iran'], ['CITEREFEkbal1991'] = template_names['Iranica'], ['CITEREFEl-Hibri2010'] = {'New Cambridge History of Islam'}, ['CITEREFEldredgeHorenstein2014'] = {'Cite concrete'}, ['CITEREFElsholz1982'] = {'Schubert\'s compositions (references)'}, ['CITEREFElwell-Sutton1984'] = template_names['Iranica'], ['CITEREFEppstein1966'] = {'Bach\'s compositions (sources)'}, ['CITEREFEppstein1982'] = {'Bach\'s compositions (sources)'}, ['CITEREFEquasis'] = {'Csr', 'Cite ship register'}, ['CITEREFEuDaly2009'] = {'Complete Book of North American Railroading'}, ['CITEREFEuDalySchaferJessupBoyd2009'] = {'Complete Book of North American Railroading'}, ----------< F >---------- ['CITEREFFacella2021'] = template_names['Iranica'], ['CITEREFFang1943'] = {'Cite ECCP'}, ['CITEREFFarinella2001'] = {'DBI'}, ['CITEREFFatehi-NezhadAzarnooshNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFFatehi-nezhadRahimi2008'] = {'Encyclopaedia Islamica'}, ['CITEREFFeder1958'] = {'Bach\'s compositions (sources)'}, ['CITEREFFederal_Writers&#039;_Project1939'] = {'Cite fednyc'}, ['CITEREFFelixMadelung1995'] = template_names['Iranica'], ['CITEREFFernandez1983'] = {'Fernandez1983'}, ['CITEREFFesharaki2015'] = {'Encyclopaedia Islamica'}, ['CITEREFFiaccadori1991'] = template_names['ODB'], ['CITEREFFikratUmar2008'] = template_names['Iranica'], ['CITEREFFine1991'] = {'The Early Medieval Balkans'}, ['CITEREFFine1994'] = {'The Late Medieval Balkans'}, ['CITEREFFletcher,_Great_Tank_Scandal'] = {'Book-Fletcher-Great Tank Scandal'}, ['CITEREFFletcher,_Universal_Tank'] = {'Book-Fletcher-Universal Tank'}, ['CITEREFFloor1992'] = template_names['Iranica'], ['CITEREFFloor2005'] = template_names['Iranica'], ['CITEREFFlora_of_North_America'] = {'EFloras'}, ['CITEREFFlora_of_North_America2009'] = {'EFloras'}, ['CITEREFFluckMarshallWilson1996'] = {'FluMarWil-LocRailCR'}, ['CITEREFFonstad1991'] = template_names['ME-ref'], ['CITEREFForkelTerry1920'] = {'Bach\'s compositions (sources)'}, ['CITEREFFornaçon,_Siegfried1957'] = template_names['NDB'], ['CITEREFForrestal1999'] = {'Forrestal-Wineries'}, ['CITEREFForster1990'] = {'Cite DCB'}, ['CITEREFFoss1991'] = template_names['ODB'], ['CITEREFFoster1971'] = template_names['ME-ref'], ['CITEREFFoster1996'] = {'Foster-Field Guide'}, ['CITEREFFrailey2010'] = {'Frailey-Twilight'}, ['CITEREFFranke1994'] = {'Cite Cambridge History of China'}, ['CITEREFFranz_Schnorr_von_Carolsfeld1883'] = {'Cite ADB'}, ['CITEREFFriedrich_Wilhelm_Bautz1975'] = {'BBKL'}, ['CITEREFFriedrich_Wilhelm_Bautz1990'] = {'BBKL'}, ['CITEREFFry1964'] = {'RCTS-LocosLNER-7'}, ['CITEREFFry1966'] = {'RCTS-LocosLNER-5'}, ['CITEREFFrye1975'] = template_names['Cam_Hist_Iran'], ['CITEREFFrye1983'] = template_names['Cam_Hist_Iran'], ['CITEREFFrye2004'] = template_names['Iranica'], ['CITEREFFubini2012'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFFudenbergTirole1991'] = {'Cite Fudenberg Tirole 1991'}, ['CITEREFFultonHarris1991'] = {'Fulton-Harris'}, ----------< G >---------- ['CITEREFGarakaniBrown2013'] = {'Encyclopaedia Islamica'}, ['CITEREFGardner2005'] = {'MSW3 Microbiotheria'}, ['CITEREFGardoni2015'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFGareyJohnson1979'] = {'Garey-Johnson'}, ['CITEREFGarsoian2000'] = template_names['Iranica'], ['CITEREFGarsoian2004'] = template_names['Iranica'], ['CITEREFGarsoian2005'] = template_names['Iranica'], ['CITEREFGarth2003'] = template_names['ME-ref'], ['CITEREFGazette34205'] = {'London Gazette'}, ['CITEREFGazette34339'] = {'London Gazette'}, ['CITEREFGazette34390'] = {'London Gazette'}, ['CITEREFGazette34427'] = {'London Gazette'}, ['CITEREFGazette34558'] = {'London Gazette'}, ['CITEREFGazette34870'] = {'London Gazette'}, ['CITEREFGazette34978'] = {'London Gazette'}, ['CITEREFGazette34989'] = {'London Gazette'}, ['CITEREFGazette35037'] = {'London Gazette'}, ['CITEREFGazette35107'] = {'London Gazette'}, ['CITEREFGazette35134'] = {'London Gazette'}, ['CITEREFGazette35284'] = {'London Gazette'}, ['CITEREFGazette37560'] = {'London Gazette'}, ['CITEREFGazette37590'] = {'London Gazette'}, ['CITEREFGazette37598'] = {'London Gazette'}, ['CITEREFGazette37610'] = {'London Gazette'}, ['CITEREFGazette38020'] = {'London Gazette'}, ['CITEREFGazette38611'] = {'London Gazette'}, ['CITEREFGeanakoplos1959'] = {'Emperor Michael Palaeologus and the West'}, ['CITEREFGeorg_von_Dadelsen1953'] = template_names['NDB'], ['CITEREFGhanoonparvar1989'] = template_names['Iranica'], ['CITEREFGhereghlou2009'] = template_names['Iranica'], ['CITEREFGhereghlou2016'] = template_names['Iranica'], ['CITEREFGhulamiyan2015'] = template_names['Iranica'], ['CITEREFGhulamiyan2015'] = {'Encyclopaedia Islamica'}, ['CITEREFGiannasi1975'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFGibb1923'] = {'The Arab Conquests in Central Asia'}, ['CITEREFGignoux1983'] = template_names['Iranica'], ['CITEREFGignoux1994'] = template_names['Iranica'], ['CITEREFGil1997'] = {'A History of Palestine, 634-1099', 'A History of Palestine, 634–1099'}, ['CITEREFGillham2001'] = {'Gillham-Waterloo-City'}, ['CITEREFGilliland1969'] = {'Gilliland'}, ['CITEREFGilliland1994'] = {'Pop Chronicles 40s'}, ['CITEREFGilliverMarshallWeiner2006'] = template_names['ME-ref'], ['CITEREFGilmanPeckColby1905'] = {'Cite NIE', 'New International Encyclopedia', 'NIE'}, ['CITEREFGilmanPeckColby1916'] = {'New International Encyclopedia', 'NIE'}, ['CITEREFGiunashvili2016'] = template_names['Iranica'], ['CITEREFGleaves1921'] = {'Gleaves'}, ['CITEREFGlischinski1997'] = {'Glischinski-Santa Fe'}, ['CITEREFGlöckner1983'] = {'Bach\'s compositions (sources)'}, ['CITEREFGoldberg1981'] = {'Goldberg-Amtrak'}, ['CITEREFGordon2001'] = {'Gordon-The Breaking of a Thousand Swords'}, ['CITEREFGraham1974'] = {'Cite DCB'}, ['CITEREFGrant1994'] = {'Grant-Death'}, ['CITEREFGrant2010'] = {'Grant-Twilight'}, ['CITEREFGrant2017'] = {'Grant-RailCo'}, ['CITEREFGrassi2018'] = template_names['Iranica'], ['CITEREFGray1986'] = template_names['Cam_Hist_Iran'], ['CITEREFGreenlaw2007'] = {'Greenlaw-Via Rail'}, ['CITEREFGregory1991'] = template_names['ODB'], ['CITEREFGregoryŠevčenko1991'] = template_names['ODB'], ['CITEREFGrete_Schemann1957'] = template_names['NDB'], ['CITEREFGrey2002'] = {'Australian Dictionary of Biography'}, ['CITEREFGrierson1903'] = {'Cite LSI', 'LSI', 'Linguistic Survey of India'}, ['CITEREFGrierson1908'] = {'Cite LSI', 'LSI', 'Linguistic Survey of India'}, ['CITEREFGrierson1919'] = {'Cite LSI', 'LSI', 'Linguistic Survey of India'}, ['CITEREFGrierson1967'] = {'Cite LSI', 'LSI', 'Linguistic Survey of India'}, ['CITEREFGriffith1991'] = template_names['ODB'], ['CITEREFGriffithsSmith1999'] = {'Griffiths-Sheds1'}, ['CITEREFGriffithsSmith2000'] = {'Griffiths-Sheds2'}, ['CITEREFGrothendieck1955'] = {'Grothendieck Produits Tensoriels Topologiques et Espaces Nucléaires'}, ['CITEREFGrothendieck1973'] = {'Grothendieck Topological Vector Spaces'}, ['CITEREFGrothendieckDieudonné1960'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1961'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1963'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1964'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1965'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1966'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1967'] = {'EGA'}, ['CITEREFGrothendieckDieudonné1971'] = {'EGA'}, ['CITEREFGroves2005'] = {'MSW3 Primates', 'MSW3 Groves'}, ['CITEREFGrubb2005'] = {'MSW3 Artiodactyla'}, ['CITEREFGuilland1967'] = {'Recherches sur les institutions byzantines'}, ['CITEREFGulino2005'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFGunzburg1984'] = {'Gunzburg-History WAGR Steam'}, ['CITEREFGurneyNabavi1993'] = template_names['Iranica'], ['CITEREFGutas1987'] = template_names['Iranica'], ['CITEREFGvakharia2001'] = template_names['Iranica'], ['CITEREFGüner1997'] = {'TDV Encyclopedia of Islam'}, ----------< H >---------- ['CITEREFHaarer2018'] = template_names['ODLA'], ['CITEREFHabibi2021'] = template_names['Iranica'], ['CITEREFHadidi2000'] = template_names['Iranica'], ['CITEREFHaji2008'] = template_names['Iranica'], ['CITEREFHaldon1999'] = {'Warfare, State and Society in the Byzantine World, 565–1204'}, ['CITEREFHalliday1985'] = {'Halliday-AustWineCompend'}, ['CITEREFHalliday2008'] = {'Halliday-JHWAtlasAust2008'}, ['CITEREFHalliday2009'] = {'Halliday-AustWineEncyc'}, ['CITEREFHalm1998'] = template_names['Iranica'], ['CITEREFHalpenny1990'] = {'Canadabio'}, ['CITEREFHambly1990'] = template_names['Cam_Hist_Iran'], ['CITEREFHambly1991'] = template_names['Cam_Hist_Iran'], ['CITEREFHammondAnderson1993'] = template_names['ME-ref'], ['CITEREFHammondScull1995'] = template_names['ME-ref'], ['CITEREFHammondScull2005'] = template_names['ME-ref'], ['CITEREFHammondScull2006a'] = template_names['ME-ref'], ['CITEREFHammondScull2006b'] = template_names['ME-ref'], ['CITEREFHanaway1988'] = template_names['Iranica'], ['CITEREFHanaway1989'] = template_names['Iranica'], ['CITEREFHanawayLewisohn2004'] = template_names['Iranica'], ['CITEREFHans_Heinrich_Borcherdt1955'] = template_names['NDB'], ['CITEREFHans_Knudsen1972'] = template_names['NDB'], ['CITEREFHansen1988'] = {'Book-Hansen-US Nuclear Weapons'}, ['CITEREFHansman1991'] = template_names['Iranica'], ['CITEREFHartshorne1977'] = {'Hartshorne AG'}, ['CITEREFHassanpour1989'] = template_names['Iranica'], ['CITEREFHassanpour1995'] = template_names['Iranica'], ['CITEREFHasumi2003'] = {'Hasumi-shiguehiko-ozu-2003'}, ['CITEREFHaswell-Smith2004'] = {'Haswell-Smith'}, ['CITEREFHaugic1908'] = {'Schaff-Herzog'}, ['CITEREFHawting1987'] = {'The First Dynasty of Islam'}, ['CITEREFHawting2000'] = {'The First Dynasty of Islam'}, ['CITEREFHaynes2011'] = {'RubberBible92nd'}, ['CITEREFHeinichen1728'] = {'Bach\'s compositions (sources)'}, ['CITEREFHeinrich_Welti1890'] = {'Cite ADB'}, ['CITEREFHelgen2005'] = {'MSW3 Scandentia'}, ['CITEREFHellmann1965'] = {'Bach\'s compositions (sources)'}, ['CITEREFHenrici1725'] = {'Bach\'s compositions (sources)'}, ['CITEREFHenryOrsmond1928'] = {'Raiatea family tree'}, ['CITEREFHermann_Palm1876'] = {'Cite ADB'}, ['CITEREFHerr2000'] = {'Herr-LN'}, ['CITEREFHeschel2007'] = {'Encyclopaedia Judaica', 'Cite EJ', 'Cite Encyclopaedia Judaica'}, ['CITEREFHewsen1988'] = template_names['Iranica'], ['CITEREFHidyHidyScottHofsummer2004'] = {'Hidy-Great Northern'}, ['CITEREFHildHellenkemper1990'] = {'Tabula Imperii Byzantini'}, ['CITEREFHildHellenkemper1994'] = {'Tabula Imperii Byzantini'}, ['CITEREFHildRestle1981'] = {'Tabula Imperii Byzantini'}, ['CITEREFHillenbrand1986'] = template_names['Iranica'], ['CITEREFHills,_Power_from_Steam'] = {'Book-Hills-Power from Steam'}, ['CITEREFHills1989'] = {'Book-Hills-Power from Steam'}, ['CITEREFHilmarJestremski2004'] = {'Schubert\'s compositions (references)'}, ['CITEREFHilton1980'] = {'Hilton-Amtrak'}, ['CITEREFHilton1990'] = {'Hilton Narrow Gauge'}, ['CITEREFHiltonDue1960'] = {'Hilton-Interurban'}, ['CITEREFHinton1986'] = {'HistoryofParliament'}, ['CITEREFHirsch1906'] = {'Cite JE1906'}, ['CITEREFHistoric_Environment_Scotland'] = {'Canmore'}, ['CITEREFHistoric_Environment_Scotland1972'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_Scotland1976'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_Scotland2020'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_Scotland:_Rusco_Tower2020'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_ScotlandLB33744'] = {'Historic Environment Scotland'}, ['CITEREFHistoric_Environment_ScotlandLB50114'] = {'Historic Environment Scotland'}, ['CITEREFHob.'] = {'Schubert\'s compositions (references)'}, ['CITEREFHoffmanSmith2005'] = {'MSW3 Lagomorpha'}, ['CITEREFHoffmann1738'] = {'Bach\'s compositions (sources)'}, ['CITEREFHofmann1983'] = {'Bach\'s compositions (sources)'}, ['CITEREFHofmann1987'] = {'Bach\'s compositions (sources)'}, ['CITEREFHofmann1999'] = {'Bach\'s compositions (sources)'}, ['CITEREFHolland1972'] = {'Holland-Vol 2'}, ['CITEREFHolland1988'] = {'Cite DCB'}, ['CITEREFHolland2001'] = {'Holland-Classic'}, ['CITEREFHollingsworth1980'] = {'Hollingsworth-Atlas-Rigby'}, ['CITEREFHollingsworth1991'] = template_names['ODB'], ['CITEREFHollingsworthCutler1991'] = template_names['ODB'], ['CITEREFHolmgren2003'] = {'EFloras'}, ['CITEREFHoltBiddle1986'] = {'Holt-NorthWest'}, ['CITEREFHolton1989'] = {'Holton-Reading-1'}, ['CITEREFHonigmann1935'] = {'Byzance et les Arabes'}, ['CITEREFHopley1983'] = {'Australian Dictionary of Biography'}, ['CITEREFHort1911'] = {'DCBL'}, ['CITEREFHorváth1966'] = {'Horváth Topological Vector Spaces and Distributions Volume 1 1966'}, ['CITEREFHosseini2017'] = template_names['Iranica'], ['CITEREFHounshell1984'] = {'Hounshell1984'}, ['CITEREFHudson1997'] = {'Country study'}, ['CITEREFHughes1990'] = {'Hughes-IndianLocos1'}, ['CITEREFHughes1992'] = {'Hughes-IndianLocos2'}, ['CITEREFHughes1994'] = {'Hughes-IndianLocos3'}, ['CITEREFHughes1996'] = {'Hughes-IndianLocos4'}, ['CITEREFHummel1943'] = {'Cite ECCP'}, ['CITEREFHumphreys2018'] = template_names['ODLA'], ['CITEREFHunter-Crawley2018'] = template_names['ODLA'], ['CITEREFHunter2008'] = {'Country study'}, ['CITEREFHutter2009'] = template_names['Iranica'], ['CITEREFHutterer2005'] = {'MSW3 Soricomorpha'}, ['CITEREFHütter2012'] = {'Hütter-50bis53'}, ['CITEREFHütter2015'] = {'Hütter-54bis59'}, ['CITEREFHütter2021'] = {'Hütter-60bis91'}, ----------< I >---------- ['CITEREFIbn_Khallikan1843'] = {'Ibn Khallikan\'s Biographical Dictionary'}, ['CITEREFImber2002'] = {'Imber-The Ottoman Empire, 1300–1650'}, ['CITEREFInalcik1989'] = {'Setton-A History of the Crusades'}, ['CITEREFIranica:_Bahrām'] = template_names['Iranica'], ['CITEREFIrvine2006'] = template_names['Iranica'], ['CITEREFIshino1998'] = {'Teishajo'}, ['CITEREFIshkevariNejad2008'] = {'Encyclopaedia Islamica'}, ['CITEREFIvey1919'] = {'Ivey-Marquette'}, ----------< J >---------- ['CITEREFJackson1908'] = {'Schaff-Herzog'}, ['CITEREFJackson1988'] = template_names['Iranica'], ['CITEREFJackson1989'] = template_names['Iranica'], ['CITEREFJackson1995'] = {'Cite enc-nyc'}, ['CITEREFJackson2010'] = {'Cite enc-nyc2'}, ['CITEREFJacksonMelville2001'] = template_names['Iranica'], ['CITEREFJacobs1904'] = {'Cite Jewish Encyclopedia'}, ['CITEREFJarchow1981'] = {'Jarchow Locally Convex Spaces'}, ['CITEREFJavadiBurrill1988'] = template_names['Iranica'], ['CITEREFJohn_O&#039;Donovan1856'] = {'Cite AFM'}, ['CITEREFJohnstonWelshSchafer2001'] = {'Johnston-Streamliner'}, ['CITEREFJones2011'] = {'Cite EPD'}, ['CITEREFJordan2002'] = {'Jordan-WineWABest'}, ['CITEREFJoshi1983'] = {'Joshi Introduction to General Topology'}, ['CITEREFJoslen2003'] = {'Joslen-OOB'}, ['CITEREFJowett1867'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFJowett1989'] = {'Jowett-Atlas', 'Carnarvonshire Railway'}, ['CITEREFJowett2000'] = {'Jowett-Nationalised'}, ['CITEREFJullien2018'] = template_names['ODLA'], ['CITEREFJupp1986'] = {'HistoryofParliament'}, ----------< K >---------- ['CITEREFK.'] = {'Schubert\'s compositions (references)'}, ['CITEREFKadinsky2016'] = {'Cite Hidden Waters NYC'}, ['CITEREFKaegi1991'] = template_names['ODB'], ['CITEREFKamaly2006'] = template_names['Iranica'], ['CITEREFKamp1981'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFKang2008'] = {'Country study'}, ['CITEREFKaramatiMelvin-Koushki2021'] = template_names['Iranica'], ['CITEREFKaramatiMelvin-Koushki2021'] = {'Encyclopaedia Islamica'}, ['CITEREFKarimi-Hakkak1997'] = template_names['Iranica'], ['CITEREFKarimiMaghsoodi2013'] = {'Encyclopaedia Islamica'}, ['CITEREFKarl_Frohnmeyer1953'] = template_names['NDB'], ['CITEREFKarnow1989'] = {'Cite-Karnow'}, ['CITEREFKasheff2001'] = template_names['Iranica'], ['CITEREFKayvaniGholami2008'] = {'Encyclopaedia Islamica'}, ['CITEREFKazhdan1991'] = template_names['ODB'], ['CITEREFKazhdanCutler1991'] = template_names['ODB'], ['CITEREFKazhdanJeffreys1991'] = template_names['ODB'], ['CITEREFKazhdanŠevčenko1991'] = template_names['ODB'], ['CITEREFKeall1987'] = template_names['Iranica'], ['CITEREFKeefe2006'] = {'Schubert\'s compositions (references)'}, ['CITEREFKeller1937'] = {'Bach\'s compositions (sources)'}, ['CITEREFKelly1988'] = {'Cite GEIL'}, ['CITEREFKellyBurrage1920'] = {'Cite AMB1920'}, ['CITEREFKennedy1998'] = {'The Cambridge History of Egypt', 'Cite Kennedy 1998', 'Cambridge History of Egypt'}, ['CITEREFKennedy2001'] = {'Kennedy-The Armies of the Caliphs'}, ['CITEREFKennedy2004'] = {'The Prophet and the Age of the Caliphates'}, ['CITEREFKennedy2007'] = {'Kennedy-The Great Arab Conquests'}, ['CITEREFKennedy2016'] = {'The Prophet and the Age of the Caliphates'}, ['CITEREFKenyon2011'] = {'Bach\'s compositions (sources)'}, ['CITEREFKerrigan1995'] = {'Shakespeare sonnets bibliography'}, ['CITEREFKettenhofen1995'] = template_names['Iranica'], ['CITEREFKettenhofen2001'] = template_names['Iranica'], ['CITEREFKettenhofenBournoutianHewsen1998'] = template_names['Iranica'], ['CITEREFKhaleelulla1982'] = {'Khaleelulla Counterexamples in Topological Vector Spaces'}, ['CITEREFKhaleghi-Motlagh1999'] = template_names['Iranica'], ['CITEREFKhaleghi-Motlagh2001'] = template_names['Iranica'], ['CITEREFKhan2012'] = {'Cite Banglapedia'}, ['CITEREFKhatibiNegahban2013'] = {'Encyclopaedia Islamica'}, ['CITEREFKim1994'] = {'Country study'}, ['CITEREFKirnberger1774'] = {'Bach\'s compositions (sources)'}, ['CITEREFKirnberger1780'] = {'Bach\'s compositions (sources)'}, ['CITEREFKlein2006'] = {'Klein-UP-2'}, ['CITEREFKlíma1988'] = template_names['Iranica'], ['CITEREFKobayashi1978'] = {'Bach\'s compositions (sources)'}, ['CITEREFKoderHild1976'] = {'Tabula Imperii Byzantini'}, ['CITEREFKoderSoustalKoder1998'] = {'Tabula Imperii Byzantini'}, ['CITEREFKoeppel2015'] = {'Cite citygrid'}, ['CITEREFKofos1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFKohler1902'] = {'Cite Jewish Encyclopedia'}, ['CITEREFKolde1914'] = {'Schaff-Herzog'}, ['CITEREFKoliopoulos1978'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFKolmogorovFomin1957'] = {'Kolmogorov Fomin Elements of the Theory of Functions and Functional Analysis'}, ['CITEREFKonrad_Ameln1985'] = template_names['NDB'], ['CITEREFKoska2011'] = {'Bach\'s compositions (sources)'}, ['CITEREFKratville1962'] = {'Kratville-SSL'}, ['CITEREFKretzschmar1910'] = {'Bach\'s compositions (sources)'}, ['CITEREFKube2009'] = {'Schubert\'s compositions (references)'}, ['CITEREFKurz1983'] = template_names['Cam_Hist_Iran'], ['CITEREFKuznik2008'] = {'Bach\'s compositions (sources)'}, ['CITEREFKöthe1969'] = {'Köthe Topological Vector Spaces I'}, ['CITEREFKöthe1979'] = {'Köthe Topological Vector Spaces II'}, ['CITEREFKöthe1983'] = {'Köthe Topological Vector Spaces I'}, ['CITEREFKülzer2008'] = {'Tabula Imperii Byzantini'}, ['CITEREFKüçükaşcı2001'] = {'TDV Encyclopedia of Islam'}, ----------< L >---------- ['CITEREFLa_Porta2018'] = template_names['ODLA'], ['CITEREFLacourcière1974'] = {'Cite DCB'}, ['CITEREFLadefogedMaddieson1996'] = {'SOWL'}, ['CITEREFLandau-Tasseron2010'] = {'New Cambridge History of Islam'}, ['CITEREFLandauCondit1996'] = {'Cite nysky'}, ['CITEREFLandmann1907'] = {'Bach\'s compositions (sources)'}, ['CITEREFLang1983'] = template_names['Cam_Hist_Iran'], ['CITEREFLangaroodiCooper2008'] = {'Encyclopaedia Islamica'}, ['CITEREFLangaroodiCooper2015'] = template_names['Iranica'], ['CITEREFLangaroodiCooper2015'] = {'Encyclopaedia Islamica'}, ['CITEREFLangaroodiNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFLangaroodiNegahban2015'] = template_names['Iranica'], ['CITEREFLangaroodiNegahban2015'] = {'Encyclopaedia Islamica'}, ['CITEREFLangaroudi2001'] = template_names['Iranica'], ['CITEREFLatham1982–2021'] = template_names['Iranica'], ['CITEREFLazard1975'] = template_names['Cam_Hist_Iran'], ['CITEREFLaërtius1925'] = {'Cite Lives of the Eminent Philosophers', 'Cite LotEP'}, ['CITEREFLeCoq1986'] = template_names['Iranica'], ['CITEREFLe_Quien1740'] = {'Oriens Christianus'}, ['CITEREFLe_Strange1900'] = {'Baghdad During the Abbasid Caliphate'}, ['CITEREFLe_Strange1905'] = {'Lands of the Eastern Caliphate'}, ['CITEREFLe_Strange1922'] = {'Baghdad During the Abbasid Caliphate'}, ['CITEREFLeblanc1979'] = {'Cite DCB'}, ['CITEREFLee1903'] = {'Cite DNBIE'}, ['CITEREFLee2018'] = template_names['ODLA'], ['CITEREFLeisingerWollny1993'] = {'Bach\'s compositions (sources)'}, ['CITEREFLerner1988'] = template_names['Iranica'], ['CITEREFLev1999'] = {'Saladin in Egypt'}, ['CITEREFLevitan2001'] = {'Springer'}, ['CITEREFLewin1925'] = {'Lewin-EarlyRail'}, ['CITEREFLewis1969'] = {'Setton-A History of the Crusades'}, ['CITEREFLewis1986'] = {'Lewis-Shortline-1986'}, ['CITEREFLewis1991'] = {'Lewis-Shortline-1991'}, ['CITEREFLewis1996'] = {'Lewis-Shortline-1996'}, ['CITEREFLewis2001'] = template_names['Iranica'], ['CITEREFLiederNet_Archive'] = {'Schubert\'s compositions (references)'}, ['CITEREFLieu1997'] = template_names['Iranica'], ['CITEREFLighthouses_of_Australia_Inc'] = {'Cite loa'}, ['CITEREFLind1986'] = {'Lind-Limiteds'}, ['CITEREFLittle1974'] = {'Cite DCB'}, ['CITEREFLongnon1969'] = {'Setton-A History of the Crusades'}, ['CITEREFLosensky2003'] = template_names['Iranica'], ['CITEREFLoverance2018'] = template_names['ODLA'], ['CITEREFLukonin1983'] = {'Cambridge History of Iran'}, ['CITEREFLurje2010'] = template_names['Iranica'], ['CITEREFLuttrell1975'] = {'Setton-A History of the Crusades'}, ['CITEREFLuttrell1987'] = {'DBI'}, ['CITEREFLynch2004'] = {'Lynch-Penn Central'}, ['CITEREFLynch2005'] = {'Lynch-New Haven passenger'}, ['CITEREFLynch2018'] = template_names['ODLA'], ['CITEREFLéger1990'] = {'Cite DCB'}, ['CITEREFle_Fleming1953'] = {'RCTS-LocosGWR-8'}, ['CITEREFle_Fleming1960'] = {'RCTS-LocosGWR-8'}, ----------< M >---------- ['CITEREFMacDermot1927'] = {'Infobox GWR'}, ['CITEREFMacDermot1931'] = {'Infobox GWR'}, ['CITEREFMacEoin1988'] = template_names['Iranica'], ['CITEREFMacKenzie1992'] = template_names['Iranica'], ['CITEREFMadelung1975'] = template_names['Cam_Hist_Iran'], ['CITEREFMadelung1978'] = {'EI2'}, ['CITEREFMadelung1983'] = template_names['Iranica'], ['CITEREFMadelung1984'] = template_names['Iranica'], ['CITEREFMadelung1988'] = template_names['Iranica'], ['CITEREFMadelung1993'] = template_names['Iranica'], ['CITEREFMadelung2003'] = template_names['Iranica'], ['CITEREFMadelungFelix1995'] = template_names['Iranica'], ['CITEREFMaeda2009'] = template_names['Iranica'], ['CITEREFMagdalino2002'] = {'The Empire of Manuel I Komnenos'}, ['CITEREFMaiken1989'] = {'Maiken-Night Trains'}, ['CITEREFMailer2004'] = {'Mailer-Omaha Road'}, ['CITEREFMajidiNegahban'] = {'Encyclopaedia Islamica'}, ['CITEREFMalandra2009'] = template_names['Iranica'], ['CITEREFManfred_Knedlik2007'] = {'BBKL'}, ['CITEREFMarshak1994'] = template_names['Iranica'], ['CITEREFMarshak2002'] = template_names['Iranica'], ['CITEREFMarshall1823'] = {'Cite RNB1823'}, ['CITEREFMarshall1824'] = {'Cite RNB1823'}, ['CITEREFMarshall1825'] = {'Cite RNB1823'}, ['CITEREFMarshall1827'] = {'Cite RNB1823'}, ['CITEREFMarshall1828'] = {'Cite RNB1823'}, ['CITEREFMarshall1829'] = {'Cite RNB1823'}, ['CITEREFMarshall1830'] = {'Cite RNB1823'}, ['CITEREFMarshall1831'] = {'Cite RNB1823'}, ['CITEREFMarshall1832'] = {'Cite RNB1823'}, ['CITEREFMarshall1833'] = {'Cite RNB1823'}, ['CITEREFMarshall1835'] = {'Cite RNB1823'}, ['CITEREFMarshall1972'] = {'Lancashire & Yorkshire Railway 3'}, ['CITEREFMarshall2001'] = {'Marshall-INGSR'}, ['CITEREFMartin_Persch1992'] = {'BBKL'}, ['CITEREFMartin_Persch1993'] = {'BBKL'}, ['CITEREFMartin_Persch1996'] = {'BBKL'}, ['CITEREFMartindale1980'] = {'Prosopography of the Later Roman Empire', 'PLRE'}, ['CITEREFMartindale1992'] = {'Prosopography of the Later Roman Empire', 'PLRE'}, ['CITEREFMartindaleJonesMorris1971'] = {'Prosopography of the Later Roman Empire', 'PLRE'}, ['CITEREFMasoud_Jalali-Moqaddam2015'] = {'Encyclopaedia Islamica'}, ['CITEREFMatini1987'] = template_names['Iranica'], ['CITEREFMatthee2008'] = template_names['Iranica'], ['CITEREFMatthee2015'] = template_names['Iranica'], ['CITEREFMaul2005'] = {'Bach\'s compositions (sources)'}, ['CITEREFMayGray2006'] = {'MayGray-WAGRPassCar'}, ['CITEREFMazzaoui2002'] = template_names['Iranica'], ['CITEREFMcArthurMcArthur2003'] = {'Cite ogn', 'Cite Oregon Geographic Names'}, ['CITEREFMcCaffrey1990'] = template_names['Iranica'], ['CITEREFMcCorduck2004'] = {'McCorduck 2004'}, ['CITEREFMcCurdyRogers1902'] = {'Cite Jewish Encyclopedia'}, ['CITEREFMcDonnell2015'] = {'McDonnell-Locomotives-2nd'}, ['CITEREFMcGhee2008'] = {'Cite McGhee 2008'}, ['CITEREFMeiningen1704'] = {'Bach\'s compositions (sources)'}, ['CITEREFMeints1992'] = {'Meints-Companies'}, ['CITEREFMeints2005'] = {'Meints-Lines'}, ['CITEREFMelamed1988'] = {'Bach\'s compositions (sources)'}, ['CITEREFMelamed1995'] = {'Bach\'s compositions (sources)'}, ['CITEREFMelville1997'] = template_names['Iranica'], ['CITEREFMelville2003'] = template_names['Iranica'], ['CITEREFMennell1892'] = {'Dictionary of Australasian Biography'}, ['CITEREFMetcalfe2009'] = {'The Muslims of Medieval Italy'}, ['CITEREFMiddleton1961'] = {'Middleton-Interurban'}, ['CITEREFMiddleton2001'] = {'Middleton-Electrified-2nd'}, ['CITEREFMiddleton2002'] = {'Middleton-PRR-Under-Wire'}, ['CITEREFMiddletonSmerkDiehl2007'] = {'Encyclopedia of North American Railroads'}, ['CITEREFMiles1975'] = template_names['Cam_Hist_Iran'], ['CITEREFMillar2011'] = {'NZR Steam Locomotive'}, ['CITEREFMiller'] = {'Encyclopaedia Islamica'}, ['CITEREFMiller1908'] = {'The Latins in the Levant', 'Latins in the Levant'}, ['CITEREFMiller1921'] = {'Essays on the Latin Orient'}, ['CITEREFMinnich2008'] = {'Country study'}, ['CITEREFMiramar_Ship_Index'] = {'Csr', 'Cite ship register'}, ['CITEREFMitchell1965'] = {'Mitchell TOC'}, ['CITEREFMittermeierKonstantHawkinsLouis2006'] = {'LoM2'}, ['CITEREFMittermeierLouisRichardsonSchwitzer2010'] = {'LoM3'}, ['CITEREFMittermeierTattersallKonstantMeyers1994'] = {'LoM1'}, ['CITEREFMoore1875'] = {'Cite CEM'}, ['CITEREFMorana1993'] = {'Bach\'s compositions (sources)'}, ['CITEREFMorony2009'] = template_names['Iranica'], ['CITEREFMoschonas1975'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFMottahedeh1975'] = template_names['Cam_Hist_Iran'], ['CITEREFMozartHaydnHaydn2008'] = {'Schubert\'s compositions (references)'}, ['CITEREFMunkres1974'] = {'Munkres Topology'}, ['CITEREFMunkres2000'] = {'Munkres Topology'}, ['CITEREFMurray2006'] = {'Murray-Illinois Central'}, ['CITEREFMusserCarleton2005'] = {'MSW3 Muroidea'}, ['CITEREFMüller,_Hans-Christian1966'] = template_names['NDB'], ----------< N >---------- ['CITEREFNSA_II,_15'] = {'Schubert\'s compositions (references)'}, ['CITEREFNSA_scores'] = {'Schubert\'s compositions (references)'}, ['CITEREFNSA_website'] = {'Schubert\'s compositions (references)'}, ['CITEREFNagel1990'] = template_names['Iranica'], ['CITEREFNariciBeckenstein2011'] = {'Narici Beckenstein Topological Vector Spaces'}, ['CITEREFNavāʾī1988'] = template_names['Iranica'], ['CITEREFNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFNersessian2018'] = template_names['ODLA'], ['CITEREFNetzer1998'] = template_names['Iranica'], ['CITEREFNetzer2007'] = template_names['Iranica'], ['CITEREFNeukirch1999'] = {'Neukirch ANT'}, ['CITEREFNeukirchSchmidtWingberg2000'] = {'Neukirch et al. CNF'}, ['CITEREFNew_York_City_Landmarks_Preservation_CommissionDolkartPostal2009'] = {'Cite nycland'}, ['CITEREFNewbould1999'] = {'Schubert\'s compositions (references)'}, ['CITEREFNewman1994'] = template_names['Iranica'], ['CITEREFNicholsonCanepaDaryaee2018'] = template_names['ODLA'], ['CITEREFNicol1988'] = {'Byzantium and Venice: A Study in Diplomatic and Cultural Relations'}, ['CITEREFNicol1992'] = {'The Immortal Emperor: The Life and Legend of Constantine Palaiologos, Last Emperor of the Romans'}, ['CITEREFNicol1993'] = {'The Last Centuries of Byzantium, 1261–1453', 'The Last Centuries of Byzantium'}, ['CITEREFNock1974'] = {'Nock-EustonGlasgow'}, ----------< O >---------- ['CITEREFO&#039;Byrne1849'] = {'Cite NBD1849'}, ['CITEREFO&#039;ConnorRobertson1996'] = {'MacTutor Biography', 'MacTutor'}, ['CITEREFO&#039;ConnorRobertson2000'] = {'MacTutor Biography', 'MacTutor'}, ['CITEREFO&#039;Donoghue1897'] = {'Cite DNB'}, ['CITEREFODB'] = template_names['ODB'], ['CITEREFODLA'] = template_names['ODLA'], ['CITEREFOberling1984'] = template_names['Iranica'], ['CITEREFOberling2008'] = template_names['Iranica'], ['CITEREFOberling2010'] = template_names['Iranica'], ['CITEREFOdisheli2018'] = template_names['ODLA'], ['CITEREFOfficial_Guide_of_the_Railways1950'] = {'Official Guide of the Railways'}, ['CITEREFOgorek2012'] = {'Ogorek-South Shore'}, ['CITEREFOikonomides1991'] = template_names['ODB'], ['CITEREFOikonomou1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFOlbrycht2021'] = template_names['Iranica'], ----------< P >---------- ['CITEREFPLP'] = {'Prosopographisches Lexikon der Palaiologenzeit', 'PLP'}, ['CITEREFPalmer1875'] = {'Cite ADB'}, ['CITEREFPalmerStewart1965'] = {'Palmer & Stewart'}, ['CITEREFPanainoAbdollahyBalland1990'] = template_names['Iranica'], ['CITEREFPandariHirtensteinNegahban2013'] = {'Encyclopaedia Islamica'}, ['CITEREFParvin2003'] = template_names['Iranica'], ['CITEREFParvin2009'] = template_names['Iranica'], ['CITEREFPatience1996'] = {'Patience-SteamTwilight'}, ['CITEREFPatton2005'] = {'MSW3 Geomyidae'}, ['CITEREFPaul2000'] = template_names['Iranica'], ['CITEREFPaxtonBourne1985'] = {'Paxton-Bourne'}, ['CITEREFPeacock2011'] = template_names['Iranica'], ['CITEREFPeck1898'] = {'HDCA'}, ['CITEREFPerlis2001'] = {'Springer'}, ['CITEREFPerreault2004'] = {'Bach\'s compositions (sources)'}, ['CITEREFPerry1983'] = template_names['Cam_Hist_Iran'], ['CITEREFPerry1990'] = template_names['Cam_Hist_Iran'], ['CITEREFPerry1991'] = template_names['Cam_Hist_Iran'], ['CITEREFPetropoulosKoumarianou1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFPetrucci1982'] = {'DBI'}, ['CITEREFPezeshk2017'] = {'Encyclopaedia Islamica'}, ['CITEREFPezeshkKhaleeli2017'] = template_names['Iranica'], ['CITEREFPezeshkKhaleeli2017'] = {'Encyclopaedia Islamica'}, ['CITEREFPfau2008'] = {'Bach\'s compositions (sources)'}, ['CITEREFPinkepank1973'] = {'Pinkepank diesel spotters guide 2'}, ['CITEREFPlantlist2016'] = {'Plantlist'}, ['CITEREFPlaten1976'] = {'Bach\'s compositions (sources)'}, ['CITEREFPloumidisAlexiou1974'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFPmbZ'] = {'Prosopographie der mittelbyzantinischen Zeit', 'PMBZ'}, ['CITEREFPolemis1968'] = {'Polemis-The Doukai'}, ['CITEREFPope2007'] = {'Encyclopaedia Judaica', 'Cite EJ', 'Cite Encyclopaedia Judaica'}, ['CITEREFPopplewell'] = {'Popplewell-Gazetteer'}, ['CITEREFPotts2018'] = template_names['ODLA'], ['CITEREFPottsCanepa2018'] = template_names['ODLA'], ['CITEREFPourshariati2017'] = {'Encyclopædia Iranica Online'}, ['CITEREFPozza1992'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFPrawer1985'] = {'Setton-A History of the Crusades'}, ['CITEREFPritsak1991'] = template_names['ODB'], ['CITEREFProsopographie_der_mittelbyz._Zeit'] = {'Prosopographie der mittelbyzantinischen Zeit'}, ----------< Q >---------- ['CITEREFQuick2009'] = {'Quick-Stations'}, ['CITEREFQuick2019'] = {'Quick-stations-5'}, ['CITEREFQuinn2003'] = template_names['Iranica'], ----------< R >---------- ['CITEREFRaditsa1983'] = template_names['Cam_Hist_Iran'], ['CITEREFRahman1983'] = template_names['Iranica'], ['CITEREFRaja&#039;i1987'] = template_names['Iranica'], ['CITEREFRamaer1974'] = {'Ramaer-SteamLocosEAR'}, ['CITEREFRansome-Wallis1971'] = {'Ransome-Wallis 1'}, ['CITEREFRateliff2007'] = template_names['ME-ref'], ['CITEREFRavegnano2000'] = {'DBI'}, ['CITEREFReed1953'] = {'RCTS-LocosGWR-2'}, ['CITEREFReed1975'] = {'Reed-Streamline era'}, ['CITEREFReed1997'] = {'Schubert\'s compositions (references)'}, ['CITEREFReinhard_Tenberg1990'] = {'BBKL'}, ['CITEREFRettinghaus2020'] = {'BDh'}, ['CITEREFReynolds1921'] = {'Cite Collier\'s', 'Collier\'s'}, ['CITEREFReynoldsOroszi2000'] = {'Reynolds-BO'}, ['CITEREFRezaHirtensteinGholami2021'] = {'Encyclopaedia Islamica'}, ['CITEREFRezakhani2018'] = template_names['ODLA'], ['CITEREFRezvani2014'] = template_names['Iranica'], ['CITEREFRichter-Bernburg2003'] = template_names['Iranica'], ['CITEREFRichter2018'] = {'BDh'}, ['CITEREFRigo2005'] = template_names['ODB'], ['CITEREFRipleyDana1863'] = {'New American Cyclopedia'}, ['CITEREFRipleyDana1864'] = {'New American Cyclopedia'}, ['CITEREFRipleyDana1879'] = {'Cite AmCyc'}, ['CITEREFRistaino1988'] = {'Country study'}, ['CITEREFRobert_Eitner1891'] = {'Cite ADB'}, ['CITEREFRobertson1983'] = {'Robertson-OriginScot'}, ['CITEREFRoe1916'] = {'Roe1916'}, ['CITEREFRoe1937'] = {'Roe1937'}, ['CITEREFRoemer1986'] = template_names['Cam_Hist_Iran'], ['CITEREFRoemer1989'] = template_names['Iranica'], ['CITEREFRoemer2004'] = template_names['Iranica'], ['CITEREFRolt1965'] = {'Rolt1965'}, ['CITEREFRoltKichenside1982'] = {'Rolt-Red'}, ['CITEREFRose1857'] = {'Cite Newgenbio'}, ['CITEREFRosenfeld1974'] = template_names['NDB'], ['CITEREFRosenzweigBlackmar1992'] = {'Cite Central Park History', 'Cite Central Park history'}, ['CITEREFRowledge1975'] = {'Rowledge-Engines of the LMS'}, ['CITEREFRowledge1993'] = {'Rowledge-Irish Steam Register'}, ['CITEREFRowlett'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2007'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2012'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2013'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2016'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowlett2017'] = {'Cite rowlett', 'Cite Rowlett'}, ['CITEREFRowson1998'] = template_names['Iranica'], ['CITEREFRudin1973'] = {'Rudin Walter Functional Analysis'}, ['CITEREFRudin1991'] = {'Rudin Walter Functional Analysis'}, ['CITEREFRunciman1951'] = {'Runciman-A History of the Crusades'}, ['CITEREFRunciman1951–1954'] = {'Runciman-A History of the Crusades'}, ['CITEREFRunciman1952'] = {'Runciman-A History of the Crusades'}, ['CITEREFRunciman1954'] = {'Runciman-A History of the Crusades'}, ['CITEREFRunciman1989'] = {'Runciman-A History of the Crusades'}, ['CITEREFRussell1985'] = {'Setton-A History of the Crusades', 'Encyclopædia Iranica Online', 'Encyclopædia Iranica', 'Encyclopaedia Iranica', 'Cite Encyclopædia Iranica Online'}, ['CITEREFRussell1986'] = template_names['Iranica'], ['CITEREFRussell1987'] = template_names['Iranica'], ['CITEREFRussellNorvig2003'] = {'Russell Norvig 2003'}, ['CITEREFRybczynski2000'] = {'Rybczynski2000'}, ['CITEREFRypka1968'] = template_names['Cam_Hist_Iran'], ----------< S >---------- ['CITEREFSR_staff2013'] = {'Houston family tree'}, ['CITEREFSadeghiTehrani2008'] = {'Encyclopaedia Islamica'}, ['CITEREFSadıkoğlu1996'] = {'TDV Encyclopedia of Islam'}, ['CITEREFSafa1987'] = template_names['Iranica'], ['CITEREFSafa1988'] = template_names['Iranica'], ['CITEREFSafa1989'] = template_names['Iranica'], ['CITEREFSafa1994'] = template_names['Iranica'], ['CITEREFSafa2003'] = template_names['Iranica'], ['CITEREFSajjadiAsatryanMelvin-Koushki'] = {'Encyclopaedia Islamica Online'}, ['CITEREFSajjadiAsatryanMelvin-Koushki'] = {'Encyclopaedia Islamica'}, ['CITEREFSajjadiAsatryanMelvin-Koushki2021'] = template_names['Iranica'], ['CITEREFSalbiev2021'] = template_names['Iranica'], ['CITEREFSalo2004'] = template_names['ME-ref'], ['CITEREFSamiʿiMelvin-Koushki2013'] = {'Encyclopaedia Islamica'}, ['CITEREFSanders1998'] = {'The Cambridge History of Egypt', 'Cambridge History of Egypt'}, ['CITEREFSanders2003'] = {'Sanders-Indiana'}, ['CITEREFSanders2006'] = {'Sanders-Heartland'}, ['CITEREFSanders2007'] = {'Sanders-Akron'}, ['CITEREFSarikakis1974'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFSaunders2001'] = {'Saunders-Merging Lines'}, ['CITEREFSaunders2013'] = {'Saunders-Giants of the Seas'}, ['CITEREFSavadaShaw1992'] = {'Country study'}, ['CITEREFSavoryKaramustafa1998'] = template_names['Iranica'], ['CITEREFScarce1986'] = template_names['Iranica'], ['CITEREFSchaeferWolff1999'] = {'Schaefer Wolff Topological Vector Spaces'}, ['CITEREFSchafer1996'] = {'Schafer-Classic-Railroads-1'}, ['CITEREFSchafer1998'] = {'Schafer-Vintage Diesel'}, ['CITEREFSchafer2000'] = {'Schafer-More-Classic'}, ['CITEREFSchafer2003'] = {'Schafer-Classic-Railroads-3'}, ['CITEREFSchaferSolomon1997'] = {'Schafer-Pennsylvania'}, ['CITEREFSchaferWelsh1997'] = {'Schafer-Classic'}, ['CITEREFSchaferWelsh2002'] = {'Schafer-Streamliners'}, ['CITEREFSchaferWelshHolland2001'] = {'Schafer-American passenger train'}, ['CITEREFSchaff-Herzog'] = {'Schaff-Herzog'}, ['CITEREFSchechter1996'] = {'Schechter Handbook of Analysis and Its Foundations'}, ['CITEREFScheide1960'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchicht1805'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchilling1997'] = {'Schilling-pop-culture'}, ['CITEREFSchindel2013'] = template_names['Iranica'], ['CITEREFSchippmann1986'] = template_names['Iranica'], ['CITEREFSchippmann1987'] = template_names['Iranica'], ['CITEREFSchlitter2005'] = {'MSW3 Tubulidentata'}, ['CITEREFSchlumberger1983'] = template_names['Cam_Hist_Iran'], ['CITEREFSchmieder1950'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchmieder1990'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchmitt1986'] = template_names['Iranica'], ['CITEREFSchmitt1989'] = template_names['Iranica'], ['CITEREFSchmitt1993'] = template_names['Iranica'], ['CITEREFSchmitt1994'] = template_names['Iranica'], ['CITEREFSchmitt1995'] = template_names['Iranica'], ['CITEREFSchmitt2002'] = template_names['Iranica'], ['CITEREFSchmitt2004'] = template_names['Iranica'], ['CITEREFSchmitt2005'] = template_names['Iranica'], ['CITEREFSchmitt2018'] = template_names['Iranica'], ['CITEREFSchmittBailey1986'] = template_names['Iranica'], ['CITEREFSchmitz1870'] = {'Cite DGRBM'}, ['CITEREFSchneider1907'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchneider1912'] = {'Bach\'s compositions (sources)'}, ['CITEREFScholze1736'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchroeter1961'] = {'Schroeter-Eisenbahnen'}, ['CITEREFSchroeterRamaer1993'] = {'Schroeter-Ramaer-Eisenbahnen'}, ['CITEREFSchubert-online'] = {'Schubert\'s compositions (references)'}, ['CITEREFSchubert1968'] = {'Schubert Topology'}, ['CITEREFSchulenberg2010'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchulenberg2013'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchulze1980'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchulze1983'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchulze1984'] = {'Bach\'s compositions (sources)'}, ['CITEREFSchwieterman2001'] = {'Schwieterman-Leaves-Eastern'}, ['CITEREFScottNegus2011'] = {'Scott-Negus-Cellar Door'}, ['CITEREFScribbins1970'] = {'Scribbins-Hiawatha'}, ['CITEREFScribbins2008'] = {'Scribbins-400-2008', 'Scribbins-Remembered'}, ['CITEREFSearle'] = {'Cite sslidx'}, ['CITEREFSegal1982'] = template_names['Iranica'], ['CITEREFSellwood1983'] = template_names['Cam_Hist_Iran'], ['CITEREFSemmensGoldfinch2000'] = {'Book-Semmens-Goldfinch-How Steam Locomotives Really Work'}, ['CITEREFSemsarZand2008'] = {'Encyclopaedia Islamica'}, ['CITEREFSetton1975'] = {'Setton-A History of the Crusades'}, ['CITEREFSetton1976'] = {'The Papacy and the Levant'}, ['CITEREFSetton1978'] = {'The Papacy and the Levant'}, ['CITEREFSetton1984'] = {'The Papacy and the Levant'}, ['CITEREFSettonHazard1975'] = {'Setton-A History of the Crusades'}, ['CITEREFSfyroeras1975'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFShahbazi1986'] = template_names['Iranica'], ['CITEREFShahbazi1987'] = template_names['Iranica'], ['CITEREFShahbazi1988'] = template_names['Iranica'], ['CITEREFShahbazi1989'] = template_names['Iranica'], ['CITEREFShahbazi1991'] = template_names['Iranica'], ['CITEREFShahbazi1994'] = template_names['Iranica'], ['CITEREFShahbazi2002'] = template_names['Iranica'], ['CITEREFShahbazi2003'] = template_names['Iranica'], ['CITEREFShahbazi2004'] = template_names['Iranica'], ['CITEREFShahbazi2005'] = template_names['Iranica'], ['CITEREFShahbaziBosworth1990'] = template_names['Iranica'], ['CITEREFShahbaziRichter-Bernburg2002'] = template_names['Iranica'], ['CITEREFShaki1991'] = template_names['Iranica'], ['CITEREFShaughnessy1997'] = {'Shaughnessy-DH'}, ['CITEREFShaw1978'] = {'Shaw-RailroadAccidents'}, ['CITEREFShayegan2004'] = template_names['Iranica'], ['CITEREFShayesteh2013'] = template_names['Iranica'], ['CITEREFSheikhsofla2018'] = {'Encyclopaedia Islamica'}, ['CITEREFShindo2004'] = {'Kaneto-shindo-shinario-jinsei'}, ['CITEREFShoarian-SattariRezaeeNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFShoshani2005'] = {'MSW3 Shoshani'}, ['CITEREFShtern2001'] = {'Springer', 'SpringerEOM'}, ['CITEREFSiegele1957'] = {'Bach\'s compositions (sources)'}, ['CITEREFSilanos2014'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFSilke2006'] = {'O\'Donnell family tree'}, ['CITEREFSimmons2005'] = {'MSW3 Chiroptera'}, ['CITEREFSimon1966'] = {'Simon-Wines Australia'}, ['CITEREFSimonWarner2011'] = {'Amtrak By the Numbers'}, ['CITEREFSinclair1911'] = {'DCBL'}, ['CITEREFSinger1905'] = {'Jewish Encyclopedia'}, ['CITEREFSix1934'] = {'Cite Six', 'Cite six'}, ['CITEREFSkjærvø2018'] = template_names['ODLA'], ['CITEREFSkoulatos1980'] = {'Les personnages byzantins de l\'Alexiade'}, ['CITEREFSloan1964'] = {'Sloan1964'}, ['CITEREFSmith1854'] = {'Cite DGRG', 'DGRG'}, ['CITEREFSmith1870'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFSmith1873'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFSmith1876'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFSmith1880'] = {'DGRBM', 'Cite DGRBM'}, ['CITEREFSmith2010'] = {'Smith-Cruise Ships-2010'}, ['CITEREFSolomentsev2001'] = {'Springer', 'SpringerEOM'}, ['CITEREFSolomon2000'] = {'Solomon-American Diesel', 'Solomon-UP'}, ['CITEREFSolomon2003'] = {'Solomon-Masterpieces'}, ['CITEREFSolomon2004'] = {'Solomon-Amtrak'}, ['CITEREFSolomon2005'] = {'Solomon-SP-Passenger'}, ['CITEREFSolomon2006'] = {'Solomon-EMD Locomotives'}, ['CITEREFSolomon2011'] = {'Solomon-Modern Diesel'}, ['CITEREFSolomon2014'] = {'Solomon-GE and EMD'}, ['CITEREFSolomonSchafer2007'] = {'Solomon-New York Central'}, ['CITEREFSolopova2009'] = template_names['ME-ref'], ['CITEREFSoucek1982'] = template_names['Iranica'], ['CITEREFSoucek1983'] = template_names['Iranica'], ['CITEREFSoustal1991'] = {'Tabula Imperii Byzantini'}, ['CITEREFSoustalKoder1981'] = {'Tabula Imperii Byzantini'}, ['CITEREFSpielhoff1991'] = {'Spielhoff-EL'}, ['CITEREFSpitta1894'] = {'Bach\'s compositions (sources)'}, ['CITEREFSpitta1899'] = {'Bach\'s compositions (sources)'}, ['CITEREFSpringirth2016'] = {'Springirth-Philadelphia'}, ['CITEREFSpuhler1986'] = template_names['Cam_Hist_Iran'], ['CITEREFSpuler1983'] = template_names['Iranica'], ['CITEREFSpuler1987'] = template_names['Iranica'], ['CITEREFStagner1993'] = {'Stagner-Transition'}, ['CITEREFStansfield1999'] = {'Stansfield-AyrRenfrew'}, ['CITEREFStatistical_Yearbook_of_the_Republic_of_Croatia_2015'] = {'Croatia Yearbook 2015'}, ['CITEREFStaufer1993'] = {'Staufer-Pennsy_III'}, ['CITEREFStauferPennypacker1962'] = {'Staufer-Pennsy'}, ['CITEREFStauferPennypacker1968'] = {'Staufer-Pennsy Power II'}, ['CITEREFStaunton1988'] = {'Australian Dictionary of Biography'}, ['CITEREFSternFishmanTilove2006'] = {'Cite New York 2000', 'Cite NY2000', 'Cite ny2000', 'Cite NY 2000', 'Cite ny 2000'}, ['CITEREFSternGilmartinMassengale1983'] = {'Cite New York 1900', 'Cite NY1900'}, ['CITEREFSternGilmartinMellins1987'] = {'Cite New York 1930', 'Cite NY 1930', 'Cite NY1930', 'Cite ny1930', 'Cite ny 1930'}, ['CITEREFSternMellinsFishman1995'] = {'Cite New York 1960', 'Cite NY1960', 'Cite NY 1960', 'Cite ny1960', 'Cite ny 1960'}, ['CITEREFSternMellinsFishman1999'] = {'Cite New York 1880', 'Cite NY1880', 'Cite NY 1880', 'Cite ny1880', 'Cite ny 1880'}, ['CITEREFStewart1974'] = {'When Steam Was King'}, ['CITEREFStrachey1981'] = template_names['ME-ref'], ['CITEREFStrickland1983'] = {'Strickland Locomotive Directory'}, ['CITEREFStähelin1909'] = {'Schaff-Herzog'}, ['CITEREFSuetin2001'] = {'Springer', 'SpringerEOM'}, ['CITEREFSundermann1988'] = template_names['Iranica'], ['CITEREFSusanne_Schurr1992'] = {'BBKL'}, ['CITEREFSusanne_Siebert1992'] = {'BBKL'}, ['CITEREFSvolopoulos1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFSwartz1992'] = {'Swartz An Introduction to Functional Analysis'}, ----------< T >---------- ['CITEREFLondon_Gazette'] = {'London Gazette'}, ['CITEREFTaber1977'] = {'Taber-DLW-19th'}, ['CITEREFTaberTaber1980'] = {'Taber-DLW-20th-1'}, ['CITEREFTaberTaber1981'] = {'Taber-DLW-20th-2'}, ['CITEREFTafazzoli1999'] = template_names['Iranica'], ['CITEREFTafazzoli1999'] = {'Encyclopaedia Islamica'}, ['CITEREFTafazzoli2000'] = template_names['Iranica'], ['CITEREFTalbot1991'] = template_names['ODB'], ['CITEREFTalbotKazhdan1991'] = template_names['ODB'], ['CITEREFTanındı2008'] = template_names['Iranica'], ['CITEREFTao2009'] = {'Cite Cambridge History of China'}, ['CITEREFTer-Ghewondyan1976'] = {'The Arab Emirates in Bagratid Armenia'}, ['CITEREFThe_London_Gazette1950'] = {'London Gazette'}, ['CITEREFThe_London_Gazette_26_September_1919'] = {'London Gazette'}, ['CITEREFThielemann2012'] = {'Bach\'s compositions (sources)'}, ['CITEREFThomas1970'] = {'HistoryofParliament'}, ['CITEREFThomas1971'] = {'Thomas-History-VI'}, ['CITEREFThrush2010'] = {'HistoryofParliament'}, ['CITEREFTikhomirov2001'] = {'Springer'}, ['CITEREFTittel1966'] = {'Bach\'s compositions (sources)'}, ['CITEREFTodt1996'] = {'BBKL'}, ['CITEREFTodtVest2014'] = {'Tabula Imperii Byzantini'}, ['CITEREFTolkien1937'] = template_names['ME-ref'], ['CITEREFTolkien1954'] = template_names['ME-ref'], ['CITEREFTolkien1955'] = template_names['ME-ref'], ['CITEREFTolkien1964'] = template_names['ME-ref'], ['CITEREFTolkien1966'] = template_names['ME-ref'], ['CITEREFTolkien1977'] = template_names['ME-ref'], ['CITEREFTolkien1980'] = template_names['ME-ref'], ['CITEREFTolkien1982'] = template_names['ME-ref'], ['CITEREFTolkien1983'] = template_names['ME-ref'], ['CITEREFTolkien1984'] = template_names['ME-ref'], ['CITEREFTolkien1985'] = template_names['ME-ref'], ['CITEREFTolkien1986'] = template_names['ME-ref'], ['CITEREFTolkien1987'] = template_names['ME-ref'], ['CITEREFTolkien1988'] = template_names['ME-ref'], ['CITEREFTolkien1989'] = template_names['ME-ref'], ['CITEREFTolkien1990'] = template_names['ME-ref'], ['CITEREFTolkien1992'] = template_names['ME-ref'], ['CITEREFTolkien1993'] = template_names['ME-ref'], ['CITEREFTolkien1994'] = template_names['ME-ref'], ['CITEREFTolkien1996'] = template_names['ME-ref'], ['CITEREFTolkien1998'] = template_names['ME-ref'], ['CITEREFTolkien1999'] = template_names['ME-ref'], ['CITEREFTolkien2007'] = template_names['ME-ref'], ['CITEREFTolkienSwan1978'] = template_names['ME-ref'], ['CITEREFTolkienTolkien1992'] = template_names['ME-ref'], ['CITEREFTonks1988'] = {'Tonks ironstone'}, ['CITEREFTonks1989'] = {'Tonks ironstone'}, ['CITEREFTonks1992'] = {'Tonks ironstone'}, ['CITEREFTopping1975'] = {'Setton-A History of the Crusades'}, ['CITEREFTorri2013'] = {'Bach\'s compositions (sources)'}, ['CITEREFTougher2018'] = template_names['ODLA'], ['CITEREFToumanoff1986'] = template_names['Iranica'], ['CITEREFToumanoff2010'] = template_names['Iranica'], ['CITEREFToumanoffChaumont1987'] = template_names['Iranica'], ['CITEREFTourret1995'] = {'Tourret-Allied Military Locomotives'}, ['CITEREFTrapp1991'] = template_names['ODB'], ['CITEREFTrappBeyerSturm-Schnabl1983'] = {'Prosopographisches Lexikon der Palaiologenzeit'}, ['CITEREFTrappWaltherBeyer1976'] = {'Prosopographisches Lexikon der Palaiologenzeit'}, ['CITEREFTrappWaltherBeyerSturm-Schnabl1978'] = {'Prosopographisches Lexikon der Palaiologenzeit'}, ['CITEREFTreadgold1988'] = {'The Byzantine Revival, 780–842'}, ['CITEREFTreadgold1997'] = {'A History of the Byzantine State and Society'}, ['CITEREFTrèves2006'] = {'Trèves François Topological vector spaces, distributions and kernels'}, ['CITEREFTucker2009'] = {'Encyclopaedia Islamica'}, ['CITEREFTurim1998'] = {'Turim-oshima'}, ['CITEREFTuring1950'] = {'Turing 1950'}, ----------< U >---------- ['CITEREFUS-NHub_Music_Deposit_31_(Klavierbüchlein_für_W._F._Bach)_at_Bach_Digital'] = {'Bach\'s compositions (sources)'}, ['CITEREFUtas2002'] = template_names['Iranica'], ['CITEREFUwe_Eckardt2001'] = {'BBKL'}, ['CITEREFunknown_author1881'] = {'Cite ADB'}, ['CITEREFunknown_author1882'] = {'Cite ADB'}, ----------< V >---------- ['CITEREFVakalopoulos1975'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFVan_Cleve1969'] = {'Setton-A History of the Crusades'}, ['CITEREFVan_Hoorickx1971'] = {'Schubert\'s compositions (references)'}, ['CITEREFVan_Hoorickx_1974–1976'] = {'Schubert\'s compositions (references)'}, ['CITEREFVan_Lint2018'] = template_names['ODLA'], ['CITEREFVan_Riemsdijk,_Compound_Locomotives'] = {'Book-Van Riemsdijk-Compound Locomotives'}, ['CITEREFVan_Tricht2011'] = {'The Latin Renovatio of Byzantium'}, ['CITEREFVandenberghen1989'] = {'Vandenberghen-SNCB12.2'}, ['CITEREFVarzos1984'] = {'Η Γενεαλογία των Κομνηνών', 'Varzos-Genealogy of the Komnenoi'}, ['CITEREFVasiliev1935'] = {'Byzance et les Arabes'}, ['CITEREFVasiliev1968'] = {'Byzance et les Arabes'}, ['CITEREFVendler1997'] = {'Shakespeare sonnets bibliography'}, ['CITEREFVenetis2012'] = template_names['Iranica'], ['CITEREFVenn1954'] = {'VennAC'}, ['CITEREFVesel1999'] = template_names['Iranica'], ['CITEREFVetter1713'] = {'Bach\'s compositions (sources)'}, ['CITEREFVevainaCanepa2018'] = template_names['ODLA'], ['CITEREFVeysey1958'] = {'Veysey-PE-1958'}, ['CITEREFVischer1912'] = {'Schaff-Herzog'}, ['CITEREFVogelsang2003'] = template_names['Iranica'], ['CITEREFVolkmer1991'] = {'Volkmer-Pennsy-Electric'}, ['CITEREFvan_Leyden1956'] = {'Bach\'s compositions (sources)'}, ['CITEREFvan_Lint2018'] = template_names['ODLA'], ['CITEREFvon_Prantl1879'] = {'Cite ADB'}, ----------< W >---------- ['CITEREFWagnerBäzoldZschechLüderitz1990'] = {'Wagner-EFA2.3.2'}, ['CITEREFWalter_Asmus1966'] = template_names['NDB'], ['CITEREFWayner1972'] = {'Wayner - Car names, numbers, consists'}, ['CITEREFWayner1973'] = {'Wayner-Spotter-2nd'}, ['CITEREFWebb2018'] = template_names['ODLA'], ['CITEREFWeber2016'] = template_names['Iranica'], ['CITEREFWechsler1979'] = {'Cite Cambridge History of China'}, ['CITEREFWegman2008'] = {'Wegman-Illustrated'}, ['CITEREFWeibel1994'] = {'Weibel IHA'}, ['CITEREFWeinrebHibbertKeayKeay2008'] = {'London encyclopedia'}, ['CITEREFWeisbrod1991'] = {'Weisbrod-EFA1.5'}, ['CITEREFWeisbrodMüllerPetznik1978'] = {'Weisbrod-EFA1.2'}, ['CITEREFWeiskopf1987'] = template_names['Iranica'], ['CITEREFWeiskopf1989'] = template_names['Iranica'], ['CITEREFWeiskopf1990'] = template_names['Iranica'], ['CITEREFWeiskopf1993'] = template_names['Iranica'], ['CITEREFWellhausen1927'] = {'The Arab Kingdom and its Fall'}, ['CITEREFWells1982'] = {'Accents of English'}, ['CITEREFWells2008'] = {'Cite LPD'}, ['CITEREFWelsh2006'] = {'Welsh-Broadway'}, ['CITEREFWelsh2008'] = {'Welsh-UP'}, ['CITEREFWerner_Raupp2001'] = {'BBKL'}, ['CITEREFWestcott1911'] = {'DCBL'}, ['CITEREFWestermayer,_Georg1882'] = {'Cite ADB'}, ['CITEREFWham1997'] = {'Wham-Ayrshire'}, ['CITEREFWharton1991'] = template_names['ODB'], ['CITEREFWhishaw1842'] = {'Whishaw-RailofGB-2ndEd'}, ['CITEREFWhishaw1969'] = {'Whishaw-RailofGB'}, ['CITEREFWhite1985'] = {'White-Passenger-1985'}, ['CITEREFWhite1993'] = {'White - American railroad freight car'}, ['CITEREFWhiteWillenskyLeadon2010'] = {'Cite aia5'}, ['CITEREFWhitehurst1973'] = {'Whitehurst GW Engines from 1940'}, ['CITEREFWhittow1996'] = {'The Making of Byzantium, 600–1025'}, ['CITEREFWickman1982'] = {'Country study'}, ['CITEREFWiesehöfer1986'] = template_names['Iranica'], ['CITEREFWiesehöfer2018'] = template_names['ODLA'], ['CITEREFWilansky2013'] = {'Wilansky Modern Methods in Topological Vector Spaces'}, ['CITEREFWillard2004'] = {'Willard General Topology'}, ['CITEREFWilliams1998'] = {'Williams-Philadelphia'}, ['CITEREFWilliams2003'] = {'Bach\'s compositions (sources)'}, ['CITEREFWilliams2014'] = template_names['Iranica'], ['CITEREFWillis1750'] = {'Cite Notitia Parliamentaria'}, ['CITEREFWilson2017'] = {'Wilson-Guide'}, ['CITEREFWilsonFiske1891'] = {'Appletons\'', 'Cite Appletons\'', 'Appletons'}, ['CITEREFWilsonFiske1892'] = {'Appletons\'', 'Cite Appletons\'', 'Appletons'}, ['CITEREFWilsonFiske1900'] = {'Appletons\'', 'Cite Appletons\'', 'Appletons'}, ['CITEREFWiltshire2000'] = {'Lloyd-Margaret River'}, ['CITEREFWinfieldLyon2004'] = {'Winfield'}, ['CITEREFWinkler1883'] = template_names['ADB'], ['CITEREFWitakowski2018'] = template_names['ODLA'], ['CITEREFWolff1969'] = {'Setton-A History of the Crusades'}, ['CITEREFWollny2015'] = {'Bach\'s compositions (sources)'}, ['CITEREFWood1907'] = {'Cite Nuttall', 'Nuttall'}, ['CITEREFWoodsKilpatrick2005'] = {'MSW3 Hystricognathi'}, ['CITEREFWorden2008'] = {'Country study'}, ['CITEREFWortley2010'] = {'John Skylitzes: A Synopsis of Byzantine History, 811–1057'}, ['CITEREFWozencraft2005'] = {'MSW3 Carnivora'}, ['CITEREFWright1979'] = {'Cite Cambridge History of China'}, ['CITEREFWright2000'] = {'Bach\'s compositions (sources)'}, ['CITEREFWägliJacobi2010'] = {'Schienennetz Schweiz'}, ['CITEREFWürsch2013'] = template_names['Iranica'], ----------< X >---------- ----------< Y >---------- ['CITEREFYakubova2016'] = template_names['Iranica'], ['CITEREFYarshater1983'] = template_names['Iranica'], ['CITEREFYarshater1986'] = template_names['Cam_Hist_Iran'], ['CITEREFYarshater1988'] = template_names['Iranica'], ['CITEREFYarshater2018'] = template_names['Iranica'], ['CITEREFYarshater2021'] = template_names['Iranica'], ['CITEREFYazici2002'] = template_names['Iranica'], ['CITEREFYenne2005'] = {'Yenne-Chiefs'}, ['CITEREFYildiz2004'] = template_names['Iranica'], ['CITEREFYonge1990'] = {'Quail-4'}, ['CITEREFYonge1994'] = {'Quail-5'}, ['CITEREFYonge2002'] = {'Quail-5'}, ['CITEREFYonge2008'] = {'Quail-5'}, ['CITEREFYonge2016'] = {'Quail-2-2016'}, ['CITEREFYongePadgettSzwenk2013'] = {'Quail-4-Paper-3rdEd'}, ['CITEREFYusofi1990'] = template_names['Iranica'], ----------< Z >---------- ['CITEREFZahn1889–1893'] = {'Bach\'s compositions (sources)'}, ['CITEREFZakeri2021'] = template_names['Iranica'], ['CITEREFZarrinkoubNegahban2008'] = {'Encyclopaedia Islamica'}, ['CITEREFZarrinkub1975'] = template_names['Cam_Hist_Iran'], ['CITEREFZeiniWiesehöfer2018'] = template_names['ODLA'], ['CITEREFZekulich2000'] = {'Zekulich-WineWA'}, ['CITEREFZimmermann2004'] = {'Zimmermann-Burlington'}, ['CITEREFZimmermann2007'] = {'Zimmermann-GrandLuxe'}, ['CITEREFZuccaric._1747'] = {'Bach\'s compositions (sources)'}, ----------< UNSORTED >---------- ['CITEREFGazette27462'] = {'London Gazette'}, ['CITEREFCawley2012'] = {'Medieval Lands by Charles Cawley'}, ['CITEREFCrone2003'] = {'Slaves on Horses'}, ['CITEREFΙστορία_του_Ελληνικού_Έθνους'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFSpyropoulos1928'] = {'Great Military and Naval Encyclopaedia'}, ['CITEREFPikros1977'] = {'Ιστορία του Ελληνικού Έθνους'}, ['CITEREFÖz1993'] = {'TDV Encyclopedia of Islam'}, ['CITEREFÖzgüdenli2008'] = template_names['Iranica'], ['CITEREFÖzaydın2002'] = {'TDV Encyclopedia of Islam'}, ['CITEREFÖzaydın2006'] = {'TDV Encyclopedia of Islam'}, ['CITEREFÖzkuyumcu2006'] = {'TDV Encyclopedia of Islam'}, ['CITEREFÖztürk2013'] = {'TDV Encyclopedia of Islam'}, ['CITEREFΜεγάλη_Στρατιωτικὴ_καὶ_Ναυτικὴ_Ἐγκυκλοπαιδεία'] = {'Great Military and Naval Encyclopaedia'}, ['CITEREFŞeşen1988'] = {'TDV Encyclopedia of Islam'}, ['CITEREFFranke1994'] = {'Cite Cambridge History of China', 'The Cambridge History of China'}, ['CITEREFTao2009'] = {'Cite Cambridge History of China', 'The Cambridge History of China'}, ['CITEREFWechsler1979'] = {'Cite Cambridge History of China', 'The Cambridge History of China'}, ['CITEREFWright1979'] = {'Cite Cambridge History of China', 'The Cambridge History of China'}, ['CITEREFHistoric_England_Benty_Grange'] = {'NHLE'}, ['CITEREFWalter1967'] = {'DBI', 'Dizionario Biografico degli Italiani'}, ['CITEREFAliprantisBorder2006'] = {'Aliprantis Border Infinite Dimensional Analysis A Hitchhiker\'s Guide Third Edition'}, ['CITEREFAmanat1985'] = template_names['Iranica'], ['CITEREFBaldwin1991'] = template_names['ODB'], ['CITEREFCallwell1999'] = {'Muni Chronology'}, ['CITEREFHalmos1982'] = {'Halmos A Hilbert Space Problem Book 1982'}, ['CITEREFHistoric_England'] = {'NHLE', 'National Heritage List for England'}, ['CITEREFHitchins2001'] = template_names['Iranica'], ['CITEREFJohnson1906'] = {'BDA1906', 'Cite BDA1906'}, ['CITEREFMachinery&#039;s_Handbook1996'] = {'MachinerysHandbook25e'}, ['CITEREFMatthee2012'] = template_names['Iranica'], ['CITEREFNicholson2018'] = template_names['ODLA'], ['CITEREFNicol1968'] = {'The Byzantine Family of Kantakouzenos'}, ['CITEREFWilsonFiske1889'] = {'Appletons\'', 'Cite Appletons\'', 'Appletons'}, } --[[--------------------------< E X P O R T E D T A B L E S >------------------------------------------------ ]] return { DNB_special_patterns = DNB_special_patterns, DNB_template_names = template_names['DNB'], special_patterns = special_patterns, whitelist = whitelist, wrapper_templates = wrapper_templates, } 1aa09b54f21ebd45d55c0e11bec8783c21d7a4fa Module:Format link 828 106 228 227 2022-09-04T15:24:59Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- Format link -- -- Makes a wikilink from the given link and display values. Links are escaped -- with colons if necessary, and links to sections are detected and displayed -- with " § " as a separator rather than the standard MediaWiki "#". Used in -- the {{format link}} template. -------------------------------------------------------------------------------- local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg local mArguments -- lazily initialise [[Module:Arguments]] local mError -- lazily initialise [[Module:Error]] local yesno -- lazily initialise [[Module:Yesno]] local p = {} -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- local function getArgs(frame) -- Fetches the arguments from the parent frame. Whitespace is trimmed and -- blanks are removed. mArguments = require('Module:Arguments') return mArguments.getArgs(frame, {parentOnly = true}) end local function removeInitialColon(s) -- Removes the initial colon from a string, if present. return s:match('^:?(.*)') end local function maybeItalicize(s, shouldItalicize) -- Italicize s if s is a string and the shouldItalicize parameter is true. if s and shouldItalicize then return '<i>' .. s .. '</i>' else return s end end local function parseLink(link) -- Parse a link and return a table with the link's components. -- These components are: -- - link: the link, stripped of any initial colon (always present) -- - page: the page name (always present) -- - section: the page name (may be nil) -- - display: the display text, if manually entered after a pipe (may be nil) link = removeInitialColon(link) -- Find whether a faux display value has been added with the {{!}} magic -- word. local prePipe, display = link:match('^(.-)|(.*)$') link = prePipe or link -- Find the page, if it exists. -- For links like [[#Bar]], the page will be nil. local preHash, postHash = link:match('^(.-)#(.*)$') local page if not preHash then -- We have a link like [[Foo]]. page = link elseif preHash ~= '' then -- We have a link like [[Foo#Bar]]. page = preHash end -- Find the section, if it exists. local section if postHash and postHash ~= '' then section = postHash end return { link = link, page = page, section = section, display = display, } end local function formatDisplay(parsed, options) -- Formats a display string based on a parsed link table (matching the -- output of parseLink) and an options table (matching the input options for -- _formatLink). local page = maybeItalicize(parsed.page, options.italicizePage) local section = maybeItalicize(parsed.section, options.italicizeSection) if (not section) then return page elseif (not page) then return mw.ustring.format('§&nbsp;%s', section) else return mw.ustring.format('%s §&nbsp;%s', page, section) end end local function missingArgError(target) mError = require('Module:Error') return mError.error{message = 'Error: no link or target specified! ([[' .. target .. '#Errors|help]])' } end -------------------------------------------------------------------------------- -- Main functions -------------------------------------------------------------------------------- function p.formatLink(frame) -- The formatLink export function, for use in templates. yesno = require('Module:Yesno') local args = getArgs(frame) local link = args[1] or args.link local target = args[3] or args.target if not (link or target) then return missingArgError('Template:Format link') end return p._formatLink{ link = link, display = args[2] or args.display, target = target, italicizePage = yesno(args.italicizepage), italicizeSection = yesno(args.italicizesection), categorizeMissing = args.categorizemissing } end function p._formatLink(options) -- The formatLink export function, for use in modules. checkType('_formatLink', 1, options, 'table') local function check(key, expectedType) --for brevity checkTypeForNamedArg( '_formatLink', key, options[key], expectedType or 'string', true ) end check('link') check('display') check('target') check('italicizePage', 'boolean') check('italicizeSection', 'boolean') check('categorizeMissing') -- Normalize link and target and check that at least one is present if options.link == '' then options.link = nil end if options.target == '' then options.target = nil end if not (options.link or options.target) then return missingArgError('Module:Format link') end local parsed = parseLink(options.link) local display = options.display or parsed.display local catMissing = options.categorizeMissing local category = '' -- Find the display text if not display then display = formatDisplay(parsed, options) end -- Handle the target option if present if options.target then local parsedTarget = parseLink(options.target) parsed.link = parsedTarget.link parsed.page = parsedTarget.page end -- Test if page exists if a diagnostic category is specified if catMissing and (mw.ustring.len(catMissing) > 0) then local title = nil if parsed.page then title = mw.title.new(parsed.page) end if title and (not title.isExternal) and (not title.exists) then category = mw.ustring.format('[[Category:%s]]', catMissing) end end -- Format the result as a link if parsed.link == display then return mw.ustring.format('[[:%s]]%s', parsed.link, category) else return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category) end end -------------------------------------------------------------------------------- -- Derived convenience functions -------------------------------------------------------------------------------- function p.formatPages(options, pages) -- Formats an array of pages using formatLink and the given options table, -- and returns it as an array. Nil values are not allowed. local ret = {} for i, page in ipairs(pages) do ret[i] = p._formatLink{ link = page, categorizeMissing = options.categorizeMissing, italicizePage = options.italicizePage, italicizeSection = options.italicizeSection } end return ret end return p b1a3177dc2ec780dc0a9720bfb64058aed46db95 Module:Hatnote 828 107 230 229 2022-09-04T15:24:59Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- Module:Hatnote -- -- -- -- This module produces hatnote links and links to related articles. It -- -- implements the {{hatnote}} and {{format link}} meta-templates and includes -- -- helper functions for other Lua hatnote modules. -- -------------------------------------------------------------------------------- local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg local mArguments -- lazily initialise [[Module:Arguments]] local yesno -- lazily initialise [[Module:Yesno]] local formatLink -- lazily initialise [[Module:Format link]] ._formatLink local p = {} -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- local curNs = mw.title.getCurrentTitle().namespace p.missingTargetCat = --Default missing target category, exported for use in related modules ((curNs == 0) or (curNs == 14)) and 'Articles with hatnote templates targeting a nonexistent page' or nil local function getArgs(frame) -- Fetches the arguments from the parent frame. Whitespace is trimmed and -- blanks are removed. mArguments = require('Module:Arguments') return mArguments.getArgs(frame, {parentOnly = true}) end local function removeInitialColon(s) -- Removes the initial colon from a string, if present. return s:match('^:?(.*)') end function p.findNamespaceId(link, removeColon) -- Finds the namespace id (namespace number) of a link or a pagename. This -- function will not work if the link is enclosed in double brackets. Colons -- are trimmed from the start of the link by default. To skip colon -- trimming, set the removeColon parameter to false. checkType('findNamespaceId', 1, link, 'string') checkType('findNamespaceId', 2, removeColon, 'boolean', true) if removeColon ~= false then link = removeInitialColon(link) end local namespace = link:match('^(.-):') if namespace then local nsTable = mw.site.namespaces[namespace] if nsTable then return nsTable.id end end return 0 end function p.makeWikitextError(msg, helpLink, addTrackingCategory, title) -- Formats an error message to be returned to wikitext. If -- addTrackingCategory is not false after being returned from -- [[Module:Yesno]], and if we are not on a talk page, a tracking category -- is added. checkType('makeWikitextError', 1, msg, 'string') checkType('makeWikitextError', 2, helpLink, 'string', true) yesno = require('Module:Yesno') title = title or mw.title.getCurrentTitle() -- Make the help link text. local helpText if helpLink then helpText = ' ([[' .. helpLink .. '|help]])' else helpText = '' end -- Make the category text. local category if not title.isTalkPage -- Don't categorise talk pages and title.namespace ~= 2 -- Don't categorise userspace and yesno(addTrackingCategory) ~= false -- Allow opting out then category = 'Hatnote templates with errors' category = mw.ustring.format( '[[%s:%s]]', mw.site.namespaces[14].name, category ) else category = '' end return mw.ustring.format( '<strong class="error">Error: %s%s.</strong>%s', msg, helpText, category ) end function p.disambiguate(page, disambiguator) -- Formats a page title with a disambiguation parenthetical, -- i.e. "Example" → "Example (disambiguation)". checkType('disambiguate', 1, page, 'string') checkType('disambiguate', 2, disambiguator, 'string', true) disambiguator = disambiguator or 'disambiguation' return mw.ustring.format('%s (%s)', page, disambiguator) end function p.defaultClasses(inline) -- Provides the default hatnote classes as a space-separated string; useful -- for hatnote-manipulation modules like [[Module:Hatnote group]]. return (inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' .. 'navigation-not-searchable' end -------------------------------------------------------------------------------- -- Hatnote -- -- Produces standard hatnote text. Implements the {{hatnote}} template. -------------------------------------------------------------------------------- function p.hatnote(frame) local args = getArgs(frame) local s = args[1] if not s then return p.makeWikitextError( 'no text specified', 'Template:Hatnote#Errors', args.category ) end return p._hatnote(s, { extraclasses = args.extraclasses, selfref = args.selfref }) end function p._hatnote(s, options) checkType('_hatnote', 1, s, 'string') checkType('_hatnote', 2, options, 'table', true) options = options or {} local inline = options.inline local hatnote = mw.html.create(inline == 1 and 'span' or 'div') local extraclasses if type(options.extraclasses) == 'string' then extraclasses = options.extraclasses end hatnote :attr('role', 'note') :addClass(p.defaultClasses(inline)) :addClass(extraclasses) :addClass(options.selfref and 'selfref' or nil) :wikitext(s) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' } } .. tostring(hatnote) end return p 7a49bd6a35a51b9e77a9c2c6f8f09a4738d7d68e Module:Hatnote/styles.css 828 108 232 231 2022-09-04T15:24:59Z SpaceMan 2 1 revision imported: Canopus text text/plain /* {{pp|small=y}} */ .hatnote { font-style: italic; } /* Limit structure CSS to divs because of [[Module:Hatnote inline]] */ div.hatnote { /* @noflip */ padding-left: 1.6em; margin-bottom: 0.5em; } .hatnote i { font-style: normal; } /* The templatestyles element inserts a link element before hatnotes. * TODO: Remove link if/when WMF resolves T200206 */ .hatnote + link + .hatnote { margin-top: -0.5em; } 44680ffd6e888866df2cdfa0341af9c7b97da94c Module:Hatnote list 828 109 234 233 2022-09-04T15:25:00Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -------------------------------------------------------------------------------- -- Module:Hatnote list -- -- -- -- This module produces and formats lists for use in hatnotes. In particular, -- -- it implements the for-see list, i.e. lists of "For X, see Y" statements, -- -- as used in {{about}}, {{redirect}}, and their variants. Also introduced -- -- are andList & orList helpers for formatting lists with those conjunctions. -- -------------------------------------------------------------------------------- local mArguments --initialize lazily local mFormatLink = require('Module:Format link') local mHatnote = require('Module:Hatnote') local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local p = {} -------------------------------------------------------------------------------- -- List stringification helper functions -- -- These functions are used for stringifying lists, usually page lists inside -- the "Y" portion of "For X, see Y" for-see items. -------------------------------------------------------------------------------- --default options table used across the list stringification functions local stringifyListDefaultOptions = { conjunction = "and", separator = ",", altSeparator = ";", space = " ", formatted = false } --Searches display text only local function searchDisp(haystack, needle) return string.find( string.sub(haystack, (string.find(haystack, '|') or 0) + 1), needle ) end -- Stringifies a list generically; probably shouldn't be used directly local function stringifyList(list, options) -- Type-checks, defaults, and a shortcut checkType("stringifyList", 1, list, "table") if #list == 0 then return nil end checkType("stringifyList", 2, options, "table", true) options = options or {} for k, v in pairs(stringifyListDefaultOptions) do if options[k] == nil then options[k] = v end end local s = options.space -- Format the list if requested if options.formatted then list = mFormatLink.formatPages( {categorizeMissing = mHatnote.missingTargetCat}, list ) end -- Set the separator; if any item contains it, use the alternate separator local separator = options.separator for k, v in pairs(list) do if searchDisp(v, separator) then separator = options.altSeparator break end end -- Set the conjunction, apply Oxford comma, and force a comma if #1 has "§" local conjunction = s .. options.conjunction .. s if #list == 2 and searchDisp(list[1], "§") or #list > 2 then conjunction = separator .. conjunction end -- Return the formatted string return mw.text.listToText(list, separator .. s, conjunction) end --DRY function function p.conjList (conj, list, fmt) return stringifyList(list, {conjunction = conj, formatted = fmt}) end -- Stringifies lists with "and" or "or" function p.andList (...) return p.conjList("and", ...) end function p.orList (...) return p.conjList("or", ...) end -------------------------------------------------------------------------------- -- For see -- -- Makes a "For X, see [[Y]]." list from raw parameters. Intended for the -- {{about}} and {{redirect}} templates and their variants. -------------------------------------------------------------------------------- --default options table used across the forSee family of functions local forSeeDefaultOptions = { andKeyword = 'and', title = mw.title.getCurrentTitle().text, otherText = 'other uses', forSeeForm = 'For %s, see %s.', } --Collapses duplicate punctuation local function punctuationCollapse (text) local replacements = { ["%.%.$"] = ".", ["%?%.$"] = "?", ["%!%.$"] = "!", ["%.%]%]%.$"] = ".]]", ["%?%]%]%.$"] = "?]]", ["%!%]%]%.$"] = "!]]" } for k, v in pairs(replacements) do text = string.gsub(text, k, v) end return text end -- Structures arguments into a table for stringification, & options function p.forSeeArgsToTable (args, from, options) -- Type-checks and defaults checkType("forSeeArgsToTable", 1, args, 'table') checkType("forSeeArgsToTable", 2, from, 'number', true) from = from or 1 checkType("forSeeArgsToTable", 3, options, 'table', true) options = options or {} for k, v in pairs(forSeeDefaultOptions) do if options[k] == nil then options[k] = v end end -- maxArg's gotten manually because getArgs() and table.maxn aren't friends local maxArg = 0 for k, v in pairs(args) do if type(k) == 'number' and k > maxArg then maxArg = k end end -- Structure the data out from the parameter list: -- * forTable is the wrapper table, with forRow rows -- * Rows are tables of a "use" string & a "pages" table of pagename strings -- * Blanks are left empty for defaulting elsewhere, but can terminate list local forTable = {} local i = from local terminated = false -- If there is extra text, and no arguments are given, give nil value -- to not produce default of "For other uses, see foo (disambiguation)" if options.extratext and i > maxArg then return nil end -- Loop to generate rows repeat -- New empty row local forRow = {} -- On blank use, assume list's ended & break at end of this loop forRow.use = args[i] if not args[i] then terminated = true end -- New empty list of pages forRow.pages = {} -- Insert first pages item if present table.insert(forRow.pages, args[i + 1]) -- If the param after next is "and", do inner loop to collect params -- until the "and"'s stop. Blanks are ignored: "1|and||and|3" → {1, 3} while args[i + 2] == options.andKeyword do if args[i + 3] then table.insert(forRow.pages, args[i + 3]) end -- Increment to next "and" i = i + 2 end -- Increment to next use i = i + 2 -- Append the row table.insert(forTable, forRow) until terminated or i > maxArg return forTable end -- Stringifies a table as formatted by forSeeArgsToTable function p.forSeeTableToString (forSeeTable, options) -- Type-checks and defaults checkType("forSeeTableToString", 1, forSeeTable, "table", true) checkType("forSeeTableToString", 2, options, "table", true) options = options or {} for k, v in pairs(forSeeDefaultOptions) do if options[k] == nil then options[k] = v end end -- Stringify each for-see item into a list local strList = {} if forSeeTable then for k, v in pairs(forSeeTable) do local useStr = v.use or options.otherText local pagesStr = p.andList(v.pages, true) or mFormatLink._formatLink{ categorizeMissing = mHatnote.missingTargetCat, link = mHatnote.disambiguate(options.title) } local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr) forSeeStr = punctuationCollapse(forSeeStr) table.insert(strList, forSeeStr) end end if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..'.')) end -- Return the concatenated list return table.concat(strList, ' ') end -- Produces a "For X, see [[Y]]" string from arguments. Expects index gaps -- but not blank/whitespace values. Ignores named args and args < "from". function p._forSee (args, from, options) local forSeeTable = p.forSeeArgsToTable(args, from, options) return p.forSeeTableToString(forSeeTable, options) end -- As _forSee, but uses the frame. function p.forSee (frame, from, options) mArguments = require('Module:Arguments') return p._forSee(mArguments.getArgs(frame), from, options) end return p d0828422b1aa0d0d0092d699d059c9e882260398 Module:Navbar 828 110 236 235 2022-09-04T15:25:00Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local p = {} local cfg = mw.loadData('Module:Navbar/configuration') local function get_title_arg(is_collapsible, template) local title_arg = 1 if is_collapsible then title_arg = 2 end if template then title_arg = 'template' end return title_arg end local function choose_links(template, args) -- The show table indicates the default displayed items. -- view, talk, edit, hist, move, watch -- TODO: Move to configuration. local show = {true, true, true, false, false, false} if template then show[2] = false show[3] = false local index = {t = 2, d = 2, e = 3, h = 4, m = 5, w = 6, talk = 2, edit = 3, hist = 4, move = 5, watch = 6} -- TODO: Consider removing TableTools dependency. for _, v in ipairs(require ('Module:TableTools').compressSparseArray(args)) do local num = index[v] if num then show[num] = true end end end local remove_edit_link = args.noedit if remove_edit_link then show[3] = false end return show end local function add_link(link_description, ul, is_mini, font_style) local l if link_description.url then l = {'[', '', ']'} else l = {'[[', '|', ']]'} end ul:tag('li') :addClass('nv-' .. link_description.full) :wikitext(l[1] .. link_description.link .. l[2]) :tag(is_mini and 'abbr' or 'span') :attr('title', link_description.html_title) :cssText(font_style) :wikitext(is_mini and link_description.mini or link_description.full) :done() :wikitext(l[3]) :done() end local function make_list(title_text, has_brackets, displayed_links, is_mini, font_style) local title = mw.title.new(mw.text.trim(title_text), cfg.title_namespace) if not title then error(cfg.invalid_title .. title_text) end local talkpage = title.talkPageTitle and title.talkPageTitle.fullText or '' -- TODO: Get link_descriptions and show into the configuration module. -- link_descriptions should be easier... local link_descriptions = { { ['mini'] = 'v', ['full'] = 'view', ['html_title'] = 'View this template', ['link'] = title.fullText, ['url'] = false }, { ['mini'] = 't', ['full'] = 'talk', ['html_title'] = 'Discuss this template', ['link'] = talkpage, ['url'] = false }, { ['mini'] = 'e', ['full'] = 'edit', ['html_title'] = 'Edit this template', ['link'] = title:fullUrl('action=edit'), ['url'] = true }, { ['mini'] = 'h', ['full'] = 'hist', ['html_title'] = 'History of this template', ['link'] = title:fullUrl('action=history'), ['url'] = true }, { ['mini'] = 'm', ['full'] = 'move', ['html_title'] = 'Move this template', ['link'] = mw.title.new('Special:Movepage'):fullUrl('target='..title.fullText), ['url'] = true }, { ['mini'] = 'w', ['full'] = 'watch', ['html_title'] = 'Watch this template', ['link'] = title:fullUrl('action=watch'), ['url'] = true } } local ul = mw.html.create('ul') if has_brackets then ul:addClass(cfg.classes.brackets) :cssText(font_style) end for i, _ in ipairs(displayed_links) do if displayed_links[i] then add_link(link_descriptions[i], ul, is_mini, font_style) end end return ul:done() end function p._navbar(args) -- TODO: We probably don't need both fontstyle and fontcolor... local font_style = args.fontstyle local font_color = args.fontcolor local is_collapsible = args.collapsible local is_mini = args.mini local is_plain = args.plain local collapsible_class = nil if is_collapsible then collapsible_class = cfg.classes.collapsible if not is_plain then is_mini = 1 end if font_color then font_style = (font_style or '') .. '; color: ' .. font_color .. ';' end end local navbar_style = args.style local div = mw.html.create():tag('div') div :addClass(cfg.classes.navbar) :addClass(cfg.classes.plainlinks) :addClass(cfg.classes.horizontal_list) :addClass(collapsible_class) -- we made the determination earlier :cssText(navbar_style) if is_mini then div:addClass(cfg.classes.mini) end local box_text = (args.text or cfg.box_text) .. ' ' -- the concatenated space guarantees the box text is separated if not (is_mini or is_plain) then div :tag('span') :addClass(cfg.classes.box_text) :cssText(font_style) :wikitext(box_text) end local template = args.template local displayed_links = choose_links(template, args) local has_brackets = args.brackets local title_arg = get_title_arg(is_collapsible, template) local title_text = args[title_arg] or (':' .. mw.getCurrentFrame():getParent():getTitle()) local list = make_list(title_text, has_brackets, displayed_links, is_mini, font_style) div:node(list) if is_collapsible then local title_text_class if is_mini then title_text_class = cfg.classes.collapsible_title_mini else title_text_class = cfg.classes.collapsible_title_full end div:done() :tag('div') :addClass(title_text_class) :cssText(font_style) :wikitext(args[1]) end return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = cfg.templatestyles } } .. tostring(div:done()) end function p.navbar(frame) return p._navbar(require('Module:Arguments').getArgs(frame)) end return p a5c8d3a8f8beb18984ea7f145ddbdf88a065d23e Module:Navbar/configuration 828 111 238 237 2022-09-04T15:25:00Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain return { ['templatestyles'] = 'Module:Navbar/styles.css', ['box_text'] = 'This box: ', -- default text box when not plain or mini ['title_namespace'] = 'Template', -- namespace to default to for title ['invalid_title'] = 'Invalid title ', ['classes'] = { -- set a line to nil if you don't want it ['navbar'] = 'navbar', ['plainlinks'] = 'plainlinks', -- plainlinks ['horizontal_list'] = 'hlist', -- horizontal list class ['mini'] = 'navbar-mini', -- class indicating small links in the navbar ['this_box'] = 'navbar-boxtext', ['brackets'] = 'navbar-brackets', -- 'collapsible' is the key for a class to indicate the navbar is -- setting up the collapsible element in addition to the normal -- navbar. ['collapsible'] = 'navbar-collapse', ['collapsible_title_mini'] = 'navbar-ct-mini', ['collapsible_title_full'] = 'navbar-ct-full' } } bbf3d86b48a5b40835e8e232ae9821e6bca390ec Module:Navbar/styles.css 828 112 240 239 2022-09-04T15:25:01Z SpaceMan 2 1 revision imported: Canopus text text/plain /* {{pp|small=yes}} */ .navbar { display: inline; font-size: 88%; font-weight: normal; } .navbar-collapse { float: left; text-align: left; } .navbar-boxtext { word-spacing: 0; } .navbar ul { display: inline-block; white-space: nowrap; line-height: inherit; } .navbar-brackets::before { margin-right: -0.125em; content: '[ '; } .navbar-brackets::after { margin-left: -0.125em; content: ' ]'; } .navbar li { word-spacing: -0.125em; } .navbar a > span, .navbar a > abbr { text-decoration: inherit; } .navbar-mini abbr { font-variant: small-caps; border-bottom: none; text-decoration: none; cursor: inherit; } .navbar-ct-full { font-size: 114%; margin: 0 7em; } .navbar-ct-mini { font-size: 114%; margin: 0 4em; } 9d4056f949b4f0b159e3d40dfb1a5f01e72f9571 Module:Navbox 828 113 242 241 2022-09-04T15:25:01Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local p = {} local navbar = require('Module:Navbar')._navbar local cfg = mw.loadData('Module:Navbox/configuration') local getArgs -- lazily initialized local args local format = string.format local function striped(wikitext, border) -- Return wikitext with markers replaced for odd/even striping. -- Child (subgroup) navboxes are flagged with a category that is removed -- by parent navboxes. The result is that the category shows all pages -- where a child navbox is not contained in a parent navbox. local orphanCat = cfg.category.orphan if border == cfg.keyword.border_subgroup and args[cfg.arg.orphan] ~= cfg.keyword.orphan_yes then -- No change; striping occurs in outermost navbox. return wikitext .. orphanCat end local first, second = cfg.class.navbox_odd_part, cfg.class.navbox_even_part if args[cfg.arg.evenodd] then if args[cfg.arg.evenodd] == cfg.keyword.evenodd_swap then first, second = second, first else first = args[cfg.arg.evenodd] second = first end end local changer if first == second then changer = first else local index = 0 changer = function (code) if code == '0' then -- Current occurrence is for a group before a nested table. -- Set it to first as a valid although pointless class. -- The next occurrence will be the first row after a title -- in a subgroup and will also be first. index = 0 return first end index = index + 1 return index % 2 == 1 and first or second end end local regex = orphanCat:gsub('([%[%]])', '%%%1') return (wikitext:gsub(regex, ''):gsub(cfg.marker.regex, changer)) -- () omits gsub count end local function processItem(item, nowrapitems) if item:sub(1, 2) == '{|' then -- Applying nowrap to lines in a table does not make sense. -- Add newlines to compensate for trim of x in |parm=x in a template. return '\n' .. item ..'\n' end if nowrapitems == cfg.keyword.nowrapitems_yes then local lines = {} for line in (item .. '\n'):gmatch('([^\n]*)\n') do local prefix, content = line:match('^([*:;#]+)%s*(.*)') if prefix and not content:match(cfg.pattern.nowrap) then line = format(cfg.nowrap_item, prefix, content) end table.insert(lines, line) end item = table.concat(lines, '\n') end if item:match('^[*:;#]') then return '\n' .. item ..'\n' end return item end -- we will want this later when we want to add tstyles for hlist/plainlist local function has_navbar() return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain and ( args[cfg.arg.name] or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '') ~= cfg.pattern.navbox ) end local function renderNavBar(titleCell) if has_navbar() then titleCell:wikitext(navbar{ [cfg.navbar.name] = args[cfg.arg.name], [cfg.navbar.mini] = 1, [cfg.navbar.fontstyle] = (args[cfg.arg.basestyle] or '') .. ';' .. (args[cfg.arg.titlestyle] or '') .. ';background:none transparent;border:none;box-shadow:none;padding:0;' }) end end local function renderTitleRow(tbl) if not args[cfg.arg.title] then return end local titleRow = tbl:tag('tr') local titleCell = titleRow:tag('th'):attr('scope', 'col') local titleColspan = 2 if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end if args[cfg.arg.image] then titleColspan = titleColspan + 1 end titleCell :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.titlestyle]) :addClass(cfg.class.navbox_title) :attr('colspan', titleColspan) renderNavBar(titleCell) titleCell :tag('div') -- id for aria-labelledby attribute :attr('id', mw.uri.anchorEncode(args[cfg.arg.title])) :addClass(args[cfg.arg.titleclass]) :css('font-size', '114%') :css('margin', '0 4em') :wikitext(processItem(args[cfg.arg.title])) end local function getAboveBelowColspan() local ret = 2 if args[cfg.arg.imageleft] then ret = ret + 1 end if args[cfg.arg.image] then ret = ret + 1 end return ret end local function renderAboveRow(tbl) if not args[cfg.arg.above] then return end tbl:tag('tr') :tag('td') :addClass(cfg.class.navbox_abovebelow) :addClass(args[cfg.arg.aboveclass]) :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.abovestyle]) :attr('colspan', getAboveBelowColspan()) :tag('div') -- id for aria-labelledby attribute, if no title :attr('id', args[cfg.arg.title] and nil or mw.uri.anchorEncode(args[cfg.arg.above])) :wikitext(processItem(args[cfg.arg.above], args[cfg.arg.nowrapitems])) end local function renderBelowRow(tbl) if not args[cfg.arg.below] then return end tbl:tag('tr') :tag('td') :addClass(cfg.class.navbox_abovebelow) :addClass(args[cfg.arg.belowclass]) :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.belowstyle]) :attr('colspan', getAboveBelowColspan()) :tag('div') :wikitext(processItem(args[cfg.arg.below], args[cfg.arg.nowrapitems])) end local function renderListRow(tbl, index, listnum, listnums_size) local row = tbl:tag('tr') if index == 1 and args[cfg.arg.imageleft] then row :tag('td') :addClass(cfg.class.noviewer) :addClass(cfg.class.navbox_image) :addClass(args[cfg.arg.imageclass]) :css('width', '1px') -- Minimize width :css('padding', '0 2px 0 0') :cssText(args[cfg.arg.imageleftstyle]) :attr('rowspan', listnums_size) :tag('div') :wikitext(processItem(args[cfg.arg.imageleft])) end local group_and_num = format(cfg.arg.group_and_num, listnum) local groupstyle_and_num = format(cfg.arg.groupstyle_and_num, listnum) if args[group_and_num] then local groupCell = row:tag('th') -- id for aria-labelledby attribute, if lone group with no title or above if listnum == 1 and not (args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group2]) then groupCell :attr('id', mw.uri.anchorEncode(args[cfg.arg.group1])) end groupCell :attr('scope', 'row') :addClass(cfg.class.navbox_group) :addClass(args[cfg.arg.groupclass]) :cssText(args[cfg.arg.basestyle]) -- If groupwidth not specified, minimize width :css('width', args[cfg.arg.groupwidth] or '1%') groupCell :cssText(args[cfg.arg.groupstyle]) :cssText(args[groupstyle_and_num]) :wikitext(args[group_and_num]) end local listCell = row:tag('td') if args[group_and_num] then listCell :addClass(cfg.class.navbox_list_with_group) else listCell:attr('colspan', 2) end if not args[cfg.arg.groupwidth] then listCell:css('width', '100%') end local rowstyle -- usually nil so cssText(rowstyle) usually adds nothing if index % 2 == 1 then rowstyle = args[cfg.arg.oddstyle] else rowstyle = args[cfg.arg.evenstyle] end local list_and_num = format(cfg.arg.list_and_num, listnum) local listText = args[list_and_num] local oddEven = cfg.marker.oddeven if listText:sub(1, 12) == '</div><table' then -- Assume list text is for a subgroup navbox so no automatic striping for this row. oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part end local liststyle_and_num = format(cfg.arg.liststyle_and_num, listnum) local listclass_and_num = format(cfg.arg.listclass_and_num, listnum) listCell :css('padding', '0') :cssText(args[cfg.arg.liststyle]) :cssText(rowstyle) :cssText(args[liststyle_and_num]) :addClass(cfg.class.navbox_list) :addClass(cfg.class.navbox_part .. oddEven) :addClass(args[cfg.arg.listclass]) :addClass(args[listclass_and_num]) :tag('div') :css('padding', (index == 1 and args[cfg.arg.list1padding]) or args[cfg.arg.listpadding] or '0 0.25em' ) :wikitext(processItem(listText, args[cfg.arg.nowrapitems])) if index == 1 and args[cfg.arg.image] then row :tag('td') :addClass(cfg.class.noviewer) :addClass(cfg.class.navbox_image) :addClass(args[cfg.arg.imageclass]) :css('width', '1px') -- Minimize width :css('padding', '0 0 0 2px') :cssText(args[cfg.arg.imagestyle]) :attr('rowspan', listnums_size) :tag('div') :wikitext(processItem(args[cfg.arg.image])) end end -- uses this now to make the needHlistCategory correct -- to use later for when we add list styles via navbox local function has_list_class(htmlclass) local class_args = { -- rough order of probability of use cfg.arg.bodyclass, cfg.arg.listclass, cfg.arg.aboveclass, cfg.arg.belowclass, cfg.arg.titleclass, cfg.arg.navboxclass, cfg.arg.groupclass, cfg.arg.imageclass } local patterns = { '^' .. htmlclass .. '$', '%s' .. htmlclass .. '$', '^' .. htmlclass .. '%s', '%s' .. htmlclass .. '%s' } for _, arg in ipairs(class_args) do for _, pattern in ipairs(patterns) do if mw.ustring.find(args[arg] or '', pattern) then return true end end end return false end local function needsHorizontalLists(border) if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then return false end return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist) end local function hasBackgroundColors() for _, key in ipairs({cfg.arg.titlestyle, cfg.arg.groupstyle, cfg.arg.basestyle, cfg.arg.abovestyle, cfg.arg.belowstyle}) do if tostring(args[key]):find('background', 1, true) then return true end end return false end local function hasBorders() for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle, cfg.arg.abovestyle, cfg.arg.belowstyle}) do if tostring(args[key]):find('border', 1, true) then return true end end return false end local function isIllegible() local styleratio = require('Module:Color contrast')._styleratio for key, style in pairs(args) do if tostring(key):match(cfg.pattern.style) then if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then return true end end end return false end local function getTrackingCategories(border) local cats = {} if needsHorizontalLists(border) then table.insert(cats, cfg.category.horizontal_lists) end if hasBackgroundColors() then table.insert(cats, cfg.category.background_colors) end if isIllegible() then table.insert(cats, cfg.category.illegible) end if hasBorders() then table.insert(cats, cfg.category.borders) end return cats end local function renderTrackingCategories(builder, border) local title = mw.title.getCurrentTitle() if title.namespace ~= 10 then return end -- not in template space local subpage = title.subpageText if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox or subpage == cfg.keyword.subpage_testcases then return end for _, cat in ipairs(getTrackingCategories(border)) do builder:wikitext('[[Category:' .. cat .. ']]') end end local function renderMainTable(border, listnums) local tbl = mw.html.create('table') :addClass(cfg.class.nowraplinks) :addClass(args[cfg.arg.bodyclass]) local state = args[cfg.arg.state] if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then if state == cfg.keyword.state_collapsed then state = cfg.class.collapsed end tbl :addClass(cfg.class.collapsible) :addClass(state or cfg.class.autocollapse) end tbl:css('border-spacing', 0) if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then tbl :addClass(cfg.class.navbox_subgroup) :cssText(args[cfg.arg.bodystyle]) :cssText(args[cfg.arg.style]) else -- regular navbox - bodystyle and style will be applied to the wrapper table tbl :addClass(cfg.class.navbox_inner) :css('background', 'transparent') :css('color', 'inherit') end tbl:cssText(args[cfg.arg.innerstyle]) renderTitleRow(tbl) renderAboveRow(tbl) local listnums_size = #listnums for i, listnum in ipairs(listnums) do renderListRow(tbl, i, listnum, listnums_size) end renderBelowRow(tbl) return tbl end local function add_navbox_styles() local frame = mw.getCurrentFrame() -- This is a lambda so that it doesn't need the frame as a parameter local function add_user_styles(templatestyles) if templatestyles and templatestyles ~= '' then return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles } } end return '' end -- get templatestyles. load base from config so that Lua only needs to do -- the work once of parser tag expansion local base_templatestyles = cfg.templatestyles local templatestyles = add_user_styles(args[cfg.arg.templatestyles]) local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles]) -- The 'navbox-styles' div exists for two reasons: -- 1. To wrap the styles to work around T200206 more elegantly. Instead -- of combinatorial rules, this ends up being linear number of CSS rules. -- 2. To allow MobileFrontend to rip the styles out with 'nomobile' such that -- they are not dumped into the mobile view. return mw.html.create('div') :addClass(cfg.class.navbox_styles) :addClass(cfg.class.nomobile) :wikitext(base_templatestyles .. templatestyles .. child_templatestyles) :done() end function p._navbox(navboxArgs) args = navboxArgs local listnums = {} for k, _ in pairs(args) do if type(k) == 'string' then local listnum = k:match(cfg.pattern.listnum) if listnum then table.insert(listnums, tonumber(listnum)) end end end table.sort(listnums) local border = mw.text.trim(args[cfg.arg.border] or args[1] or '') if border == cfg.keyword.border_child then border = cfg.keyword.border_subgroup end -- render the main body of the navbox local tbl = renderMainTable(border, listnums) local res = mw.html.create() -- render the appropriate wrapper for the navbox, based on the border param if border == cfg.keyword.border_none then res:node(add_navbox_styles()) local nav = res:tag('div') :attr('role', 'navigation') :node(tbl) -- aria-labelledby title, otherwise above, otherwise lone group if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then nav:attr( 'aria-labelledby', mw.uri.anchorEncode( args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1] ) ) else nav:attr('aria-label', cfg.aria_label) end elseif border == cfg.keyword.border_subgroup then -- We assume that this navbox is being rendered in a list cell of a -- parent navbox, and is therefore inside a div with padding:0em 0.25em. -- We start with a </div> to avoid the padding being applied, and at the -- end add a <div> to balance out the parent's </div> res :wikitext('</div>') :node(tbl) :wikitext('<div>') else res:node(add_navbox_styles()) local nav = res:tag('div') :attr('role', 'navigation') :addClass(cfg.class.navbox) :addClass(args[cfg.arg.navboxclass]) :cssText(args[cfg.arg.bodystyle]) :cssText(args[cfg.arg.style]) :css('padding', '3px') :node(tbl) -- aria-labelledby title, otherwise above, otherwise lone group if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then nav:attr( 'aria-labelledby', mw.uri.anchorEncode(args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]) ) else nav:attr('aria-label', cfg.aria_label) end end if (args[cfg.arg.nocat] or cfg.keyword.nocat_false):lower() == cfg.keyword.nocat_false then renderTrackingCategories(res, border) end return striped(tostring(res), border) end function p.navbox(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end args = getArgs(frame, {wrappers = {cfg.pattern.navbox}}) -- Read the arguments in the order they'll be output in, to make references -- number in the right order. local _ _ = args[cfg.arg.title] _ = args[cfg.arg.above] -- Limit this to 20 as covering 'most' cases (that's a SWAG) and because -- iterator approach won't work here for i = 1, 20 do _ = args[format(cfg.arg.group_and_num, i)] _ = args[format(cfg.arg.list_and_num, i)] end _ = args[cfg.arg.below] return p._navbox(args) end return p 5bbd6589b208bd567b351b855083c132c16a0fb9 Module:Navbox/configuration 828 114 244 243 2022-09-04T15:25:01Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain return { aria_label = 'Navbox', nowrap_item = '%s<span class="nowrap">%s</span>', templatestyles = mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Module:Navbox/styles.css' } }, -- do not localize marker table marker = { oddeven = '\127_ODDEVEN_\127', restart = '\127_ODDEVEN0_\127', regex = '\127_ODDEVEN(%d?)_\127' }, category = { orphan = '[[Category:Navbox orphans]]', horizontal_lists = 'Navigational boxes without horizontal lists', background_colors = 'Navboxes using background colours', illegible = 'Potentially illegible navboxes', borders = 'Navboxes using borders', }, keyword = { border_subgroup = 'subgroup', border_child = 'child', border_none = 'none', evenodd_swap = 'swap', navbar_off = 'off', navbar_plain = 'plain', nocat_false = 'false', nowrapitems_yes = 'yes', orphan_yes = 'yes', state_collapsed = 'collapsed', state_off = 'off', state_plain = 'plain', subpage_doc = 'doc', subpage_sandbox = 'sandbox', subpage_testcases = 'testcases', tracking_no = 'no' }, class = { autocollapse = 'autocollapse', collapsible = 'mw-collapsible', collapsed = 'mw-collapsed', -- Warning navbox = 'navbox', -- WMF currently hides 'navbox' from mobile, -- so you probably shouldn't change the navbox class. navbox_abovebelow = 'navbox-abovebelow', navbox_group = 'navbox-group', navbox_image = 'navbox-image', navbox_inner = 'navbox-inner', navbox_list = 'navbox-list', navbox_list_with_group = 'navbox-list-with-group', navbox_part = 'navbox-', -- do not l10n navbox_styles = 'navbox-styles', navbox_subgroup = 'navbox-subgroup', navbox_title = 'navbox-title', -- l10n only if you change pattern.navbox_title below navbox_odd_part = 'odd', -- do not l10n navbox_even_part = 'even', -- do not l10n nomobile = 'nomobile', nowraplinks = 'nowraplinks', noviewer = 'noviewer' -- used to remove images from MediaViewer }, pattern = { listnum = '^list(%d+)$', sandbox = '/sandbox$', navbox = 'Template:Navbox', nowrap = '^<span class="nowrap">', style = 'style$', navbox_title = '<th[^>]*"navbox%-title"', hlist = 'hlist', plainlist = 'plainlist' }, arg = { above = 'above', aboveclass = 'aboveclass', abovestyle = 'abovestyle', basestyle = 'basestyle', bodyclass = 'bodyclass', bodystyle = 'bodystyle', border = 'border', below = 'below', belowclass = 'belowclass', belowstyle = 'belowstyle', evenodd = 'evenodd', evenstyle = 'evenstyle', group1 = 'group1', group2 = 'group2', group_and_num = 'group%d', groupstyle_and_num = 'group%dstyle', groupclass = 'groupclass', groupstyle = 'groupstyle', groupwidth = 'groupwidth', innerstyle = 'innerstyle', image = 'image', imageclass = 'imageclass', imageleft = 'imageleft', imageleftstyle = 'imageleftstyle', imagesetyle = 'imagestyle', list_and_num = 'list%d', listclass_and_num = 'list%dclass', liststyle_and_num = 'list%dstyle', list1padding = 'list1padding', listclass = 'listclass', listpadding = 'listpadding', liststyle = 'liststyle', name = 'name', navbar = 'navbar', navboxclass = 'navboxclass', nocat = 'nocat', nowrapitems = 'nowrapitems', oddstyle = 'oddstyle', orphan = 'orphan', state = 'state', style = 'style', templatestyles = 'templatestyles', child_templatestyles = 'child templatestyles', title = 'title', titleclass = 'titleclass', titlestyle = 'titlestyle', tracking = 'tracking' }, -- names of navbar arguments navbar = { name = 1, fontstyle = 'fontstyle', mini = 'mini' } } 4a1fb97efbf7aa8a852959457b43eab420073194 Module:Navbox/styles.css 828 115 246 245 2022-09-04T15:25:02Z SpaceMan 2 1 revision imported: Canopus text text/plain /* {{pp|small=y}} */ .navbox { box-sizing: border-box; border: 1px solid #a2a9b1; width: 100%; clear: both; font-size: 88%; text-align: center; padding: 1px; margin: 1em auto 0; /* Prevent preceding content from clinging to navboxes */ } .navbox .navbox { margin-top: 0; /* No top margin for nested navboxes */ } .navbox + .navbox, /* TODO: remove first line after transclusions have updated */ .navbox + .navbox-styles + .navbox { margin-top: -1px; /* Single pixel border between adjacent navboxes */ } .navbox-inner, .navbox-subgroup { width: 100%; } .navbox-group, .navbox-title, .navbox-abovebelow { padding: 0.25em 1em; line-height: 1.5em; text-align: center; } .navbox-group { white-space: nowrap; /* @noflip */ text-align: right; } .navbox, .navbox-subgroup { background-color: #fdfdfd; } .navbox-list { line-height: 1.5em; border-color: #fdfdfd; /* Must match background color */ } .navbox-list-with-group { text-align: left; border-left-width: 2px; border-left-style: solid; } /* cell spacing for navbox cells */ /* Borders above 2nd, 3rd, etc. rows */ /* TODO: figure out how to replace tr as structure; * with div structure it should be just a matter of first-child */ tr + tr > .navbox-abovebelow, tr + tr > .navbox-group, tr + tr > .navbox-image, tr + tr > .navbox-list { border-top: 2px solid #fdfdfd; /* Must match background color */ } .navbox-title { background-color: #ccf; /* Level 1 color */ } .navbox-abovebelow, .navbox-group, .navbox-subgroup .navbox-title { background-color: #ddf; /* Level 2 color */ } .navbox-subgroup .navbox-group, .navbox-subgroup .navbox-abovebelow { background-color: #e6e6ff; /* Level 3 color */ } .navbox-even { background-color: #f7f7f7; } .navbox-odd { background-color: transparent; } /* TODO: figure out how to remove reliance on td as structure */ .navbox .hlist td dl, .navbox .hlist td ol, .navbox .hlist td ul, .navbox td.hlist dl, .navbox td.hlist ol, .navbox td.hlist ul { padding: 0.125em 0; } .navbox .navbar { display: block; font-size: 100%; } .navbox-title .navbar { /* @noflip */ float: left; /* @noflip */ text-align: left; /* @noflip */ margin-right: 0.5em; } e80b0d7a5770e6e105dab832deb6c37a5245ebc6 Module:Other uses 828 116 248 247 2022-09-04T15:25:02Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain local mHatnote = require('Module:Hatnote') local mHatlist = require('Module:Hatnote list') local mArguments --initialize lazily local mTableTools --initialize lazily local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local p = {} -- Produces standard {{other uses}} implementation function p.otheruses(frame) mArguments = require('Module:Arguments') mTableTools = require('Module:TableTools') local args = mTableTools.compressSparseArray(mArguments.getArgs(frame)) local title = mw.title.getCurrentTitle().prefixedText return p._otheruses(args, {title=title}) end --Implements "other [x]" templates with otherText supplied at invocation function p.otherX(frame) mArguments = require('Module:Arguments') mTableTools = require('Module:TableTools') local x = frame.args[1] local args = mTableTools.compressSparseArray( mArguments.getArgs(frame, {parentOnly = true}) ) local options = { title = mw.title.getCurrentTitle().prefixedText, otherText = x } return p._otheruses(args, options) end -- Main generator function p._otheruses(args, options) --Type-checks and defaults checkType('_otheruses', 1, args, 'table', true) args = args or {} checkType('_otheruses', 2, options, 'table') if not (options.defaultPage or options.title) then error('No default title data provided in "_otheruses" options table', 2) end local emptyArgs = true for k, v in pairs(args) do if type(k) == 'number' then emptyArgs = false break end end if emptyArgs then args = { options.defaultPage or mHatnote.disambiguate(options.title, options.disambiguator) } end --Generate and return hatnote local text = mHatlist.forSeeTableToString({{ use = options.otherText and "other " .. options.otherText or nil, pages = args }}) return mHatnote._hatnote(text) end return p 2497cafae11ffa785bced56bc9f3853cf3bce7b1 Module:Portal/images/a 828 117 250 249 2022-09-04T15:25:03Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[==[ This is the "A" list of portal image names. It contains a list of portal images for use with [[Module:Portal]] -- for portal names that start with the letter "A". For aliases to existing portal names, and for portal names that -- start with other letters, please use the appropriate page from the following list: -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/o]] - for portal names beginning with "O". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/s]] - for portal names beginning with "S". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- [[Module:Portal/images/aliases]] - for adding aliases for existing portal names. Use this page for variations -- in spelling and diacritics, etc., no matter what letter the portal begins with. -- When adding entries, please use alphabetical order. The format of the images table entries is as follows: -- ["portal name"] = "image.svg", -- The portal name should be the name of your portal, in lower case. For example, the portal name for -- "Portal:United Kingdom" would be "united kingdom". The image name should be capitalised normally, and the "File:" -- namespace prefix should be -- omitted. ]==] return { ["airports"] = "Round Landmark Icon Airport.svg|link=|alt=", ["aarhus"] = "Coat of arms of Aarhus.svg|alt=icon", ["abkhazia"] = "Flag of Abkhazia.svg|border|link=|alt=flag", ["aboriginal peoples in canada"] = "Aboriginal War Veterans monument (close).JPG|alt=icon", ["abu dhabi"] = "Flag of Abu Dhabi.svg|border|link=|alt=flag", ["acipenseriformes"] = "Acipenser oxyrhynchus (edit).png|link=|alt=icon", ["actors and filmmakers"] = "Charlie Chaplin 1912.jpg|link=|alt=photo", ["ac/dc"] = "Acdc logo band.svg|link=|alt=", ["academy award"] = "Video-x-generic.svg|link=|alt=", ["acadia"] = "Flag of Acadia.svg|border|link=|alt=flag", ["acc"] = "ACC Map crop 2014.png|alt=icon", ["adelaide"] = "Escudo de Adelaida.png|alt=icon", ["adobe flash"] = "Adobe Flash Player v11 icon.png|link=|alt=logo", ["advent"] = "Candle4.png|alt=Advent candle", ["aerosmith"] = "Joe Perry 1.jpg|alt=icon", ["aerospace biography"] = "Armstrong-Spencom01.jpg|link=|alt=photo", ["aesthetics"] = "Morning Glory Flower square.jpg|alt=icon", ["afghanistan"] = "Flag of the Taliban.svg|border|link=|alt=flag", ["africa"] = "Africa (orthographic projection).svg|link=|alt=map", ["african american"] = "Kleed- Stichting Nationaal Museum van Wereldculturen - RV-5899-18 (cropped).jpg|alt=icon", ["african cuisine"] = "Africa icon.png|link=|alt=", ["african diaspora"] = "Moromi.png|link=|alt=map", ["african union"] = "Flag of the African Union.svg|border|link=|alt=flag", ["afro-eurasia"] = "Afro-Eurasia (orthographic projection).svg|link=|alt=map", ["agriculture"] = "Veranotrigo.jpg|alt=icon", ["agriculture and agronomy"] = "Veranotrigo.jpg|alt=icon", ["agropedia"] = "Farmer plowing in Fahrenwalde, Mecklenburg-Vorpommern, Germany.jpg|alt=icon", ["aguascalientes"] = "Flag of Aguascalientes.svg|border|link=|alt=flag", ["ahmadiyya"] = "White Minaret Symbol.png|alt=icon", ["ahmedabad"] = "Mosque of Sidi Sayed Jaali.JPG|alt=icon", ["ai"] = "ArtificialFictionBrain.png|alt=icon", ["ajman"] = "Flag of Ajman.svg|link=|alt=flag", ["akb48"] = "AKB48 logo2.svg|link=|alt=", ["alabama"] = "Flag of Alabama.svg|border|link=|alt=flag", ["alaska"] = "Flag of Alaska.svg|border|link=|alt=flag", ["albania"] = "Flag of Albania.svg|border|link=|alt=flag", ["albemarle county"] = "Monticello 2010-10-29.jpg|link=|alt=photo", ["alberta"] = "Flag of Alberta.svg|border|link=|alt=flag", ["alcoholic drinks"] = "Mitch (cocktail).jpg|link=|alt=", ["a-league"] = "Soccer ball.svg|alt=icon", ["algae"] = "Algae Graphic.svg|link=|alt=icon", ["algebra"] = "Arithmetic symbols.svg|link=|alt=", ["algeria"] = "Flag of Algeria.svg|border|link=|alt=flag", ["almaty"] = "Flag of Almaty.svg|alt=flag", ["alps"] = "Palü en Diavolezza.jpg|alt=icon", ["alternative medicine"] = "Rod of Asclepius2.svg|alt=icon", ["alternative rock"] = "Guitar 1.svg|link=|alt=icon", ["american animation"] = "Animation disc US.svg|link=|alt=icon", ["american cinema"] = "Cinema of the United States.svg|link=|alt=icon", ["american civil war"] = "Acw bs 7a.png|border|link=|alt=", ["american cuisine"] = "Americanbandstand-1.jpg|link=|alt=", ["american football"] = "American football.svg|link=|alt=icon", ["american football league"] = "AFL Trophy alt.png|link=|alt=trophy", ["american music"] = "Musical Notes USA.svg|link=|alt=icon", ["american old west"] = "Frederic Remington Dismounted Moving Led Horses.jpg|link=|alt=painting", ["american open wheel racing"] = "JuanMontoya2015Indy500.JPG|link=|alt=photo", ["american revolutionary war"] = "Washington Crossing the Delaware by Emanuel Leutze, MMA-NYC, 1851.jpg|border|link=|alt=", ["american samoa"] = "Flag of American Samoa.svg|border|link=|alt=flag", ["american television"] = "USA flag on television.svg|link=|alt=icon", ["americas"] = "Americas (orthographic projection).svg|link=|alt=map", ["amiga"] = "Boingball.png|link=|alt=", ["amphibians"] = "Frog (2546) - The Noun Project.svg|link=|alt=", ["amphibians and reptiles"] = "Lizardicon.svg|link=|alt=", ["amusement parks"] = "Roller Coaster Icon.svg|link=|alt=", ["anabaptism"] = "Dirk.willems.rescue.ncs.jpg|link=|alt=", ["analysis"] = "Nuvola apps kmplot.svg|alt=icon", ["analytical chemistry"] = "Nuvola apps edu science.svg|alt=icon", ["anarchism"] = "BlackFlagSymbol.svg|border|link=|alt=flag", ["andes"] = "Ausangate-hillside-MT.jpg|alt=", ["andorra la vella"] = "Flag of Andorra la Vella.svg|alt=flag", ["apples"] = "Apple icon 1.png|link=|alt=", ["argentine cuisine"] = "Argentine cuisine title.jpg|link=|alt=", ["anatomy"] = "Anatomy posture and body mechanics 08.web.jpg|alt=icon", ["ancient egypt"] = "Pyramidi aavikolla.png|link=|alt=", ["ancient germanic culture"] = "Mjollnir icon.png|link=|alt=", ["ancient greece"] = "Parthenon from west.jpg|link=|alt=", ["ancient japan"] = "Shiki no Fuji, Ōmuro fukin by Takahashi Shōtei.jpg|link=|alt=", ["ancient near east"] = "Babylonlion.JPG|link=|alt=", ["ancient rome"] = "SPQRomani.svg|link=|alt=", ["andaman and nicobar islands"] = "India Andaman and Nicobar Islands locator map.svg|border|link=|alt=map", ["andhra pradesh"] = "Archbridgegodavari.JPG|alt=icon", ["andorra"] = "Flag of Andorra.svg|border|link=|alt=flag", ["android (operating system)"] = "Android robot.svg|link=|alt=icon", ["anglicanism"] = "Canterbury cathedral.jpg|link=|alt=", ["anglo-saxon england"] = "Peterborough Chronicle cropped.jpg|link=|alt=", ["angola"] = "Flag of Angola.svg|border|link=|alt=flag", ["anguilla"] = "Flag of Anguilla.svg|border|link=|alt=flag", ["animal rights"] = "Paw (Animal Rights symbol).svg|alt=icon", ["animals"] = "Caribou from Wagon Trails.jpg|alt=icon", ["animation"] = "Animation disc.svg|alt=icon", ["animation/canadian animation work group"] = "Animation disc Maple Leaf.svg|alt=icon", ["anime and manga"] = "Wikipe-tan face.svg|alt=icon", ["antarctica"] = "Antarctica (orthographic projection).svg|link=|alt=map", ["anthropology"] = "Moai Easter Island InvMH-35-61-1.jpg|link=|alt=", ["antigua and barbuda"] = "Flag of Antigua and Barbuda.svg|border|link=|alt=flag", ["antwerp"] = "Coat of arms of Antwerp (City).svg|alt=icon", ["appalachia"] = "Appalachian region of United States.png|border|link=|alt=map", ["apple inc."] = "Apple logo black.svg|link=|alt=", ["applied science"] = "Metallurgy stub icon.svg|link=|alt=icon", ["aquarium fish"] = "Pterois antennata-3.jpg|link=|alt=", ["arab world"] = "Flag of the Arab League.svg|border|link=|alt=flag", ["arabic language"] = "Arabic-dad-letter.svg|link=Arabic language|alt=icon", ["archaeology"] = "Stonehenge Closeup.jpg|link=|alt=", ["architecture"] = "P parthenon.svg|alt=icon", ["arctic"] = "Arctic (orthographic projection).svg|link=|alt=map", ["argentina"] = "Flag of Argentina.svg|border|link=|alt=flag", ["arithmetic"] = "Arithmetic symbols.svg|link=|alt=", ["arizona"] = "Flag of Arizona.svg|border|link=|alt=flag", ["arkansas"] = "Flag of Arkansas.svg|border|link=|alt=flag", ["armenia"] = "Flag of Armenia.svg|border|link=|alt=flag", ["arminianism"] = "Arminius 5 flopped and cropped.png|link=|alt=", ["arunachal pradesh"] = "India Arunachal Pradesh locator map.svg|link=|alt=map", ["art"] = "Ballerina-icon.jpg|alt=icon", ["arthropods"] = "Cercophonius squama.jpg|alt=icon", ["artificial intelligence"] = "Animation2.gif|alt=icon", ["arts"] = "Nuvola apps package graphics.png|alt=icon", ["artsakh"] = "Flag of Artsakh.svg|border|link=|alt=flag", ["arts and entertainment"] = "Meryl in 1990.jpg|link=|alt=photo", ["aruba"] = "Flag of Aruba.svg|border|link=|alt=flag", ["asia"] = "Asia (orthographic projection).svg|alt=icon", ["asian games"] = "Asian Games logo01.png|link=|alt=", ["aspect ratio 1.000"] = "Flag of Switzerland.svg|link=|alt=image", ["aspect ratio 1.333"] = "Flag of Gabon.svg|link=|alt=image", ["aspect ratio 1.400"] = "Flag of Kosovo.svg|link=|alt=image", ["aspect ratio 1.500"] = "Flag of the European Union.svg|link=|alt=image", ["aspect ratio 1.667"] = "Flag of Bangladesh.svg|link=|alt=image", ["aspect ratio 2.000"] = "Flag of the United Kingdom.svg|link=|alt=image", ["assam"] = "Seal of Assam.png|link=|alt=", ["association football"] = "Soccer ball.svg|alt=icon", ["assyrians"] = "Flag of Assyria.svg|border|link=|alt=flag", ["astrobiology"] = "PIA01130 Interior of Europa.jpg|link=|alt=", ["astrology"] = "Astrologia-tynkä.jpg|link=|alt=", ["astronomy"] = "Crab Nebula.jpg|link=|alt=", ["atheism"] = "Atheism template.svg|alt=icon", ["athletics"] = "Athletics pictogram.svg|link=|alt=", ["atlanta"] = "Atlflag.svg|link=|alt=flag", ["atlantic ocean"] = "Atlantic Ocean - en IHO.png|link=|alt=map", ["atlas"] = "World map green.png|alt=icon", ["atmospheric science"] = "Cumulus clouds in fair weather.jpeg|link=|alt=icon", ["atoms"] = "Stylised atom with three Bohr model orbits and stylised nucleus.svg|link=|alt=", ["austin"] = "Sixth Street Austin.jpg|alt=icon", ["australasia"] = "Oceania (orthographic projection).svg|link=|alt=map", ["australia"] = "Flag of Australia.svg|border|link=|alt=flag", ["australian army"] = "Australian Army Emblem Transparent.png|border|link=|alt=icon", ["australian capital territory"] = "Flag of the Australian Capital Territory.svg|border|link=|alt=flag", ["australian continent"] = "Australia (orthographic projection).svg|link=|alt=map", ["australian roads"] = "Australia road sign W5-29.svg|alt=icon", ["australian rules football"] = "Sherrin-transparent.png|link=|alt=", ["austria"] = "Flag of Austria.svg|border|link=|alt=flag", ["austria-hungary"] = "Wappen Österreich-Ungarn 1916 (Klein).png|link=|alt=", ["automobiles"] = "Sportcar sergio luiz ara 01.svg|link=|alt=", ["automotive industry in japan"] = "Car with Driver-Silhouette.svg|link=|alt=", ["aviation"] = "Aviacionavion.png|link=|alt=", ["avril lavigne"] = "LetGo.jpg|alt=icon", ["ayyavazhi"] = "Ayyavazh logo transperent.png|alt=icon", ["azad kashmir"] = "Flag of Azad Kashmir.svg|border|link=|alt=flag", ["azerbaijan"] = "Flag of Azerbaijan.svg|border|link=|alt=flag", ["azores"] = "Flag of the Azores.svg|border|link=|alt=flag" } 2ed9709a584c9486757ce4112bbf87096eb6b3be Module:Portal bar 828 118 252 251 2022-09-04T15:25:03Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module implements {{portal bar}}. require('Module:No globals') -- determine whether we're being called from a sandbox local isSandbox = mw.getCurrentFrame():getTitle():find('sandbox', 1, true) local sandbox = isSandbox and '/sandbox' or '' local portalModule = require('Module:Portal'..sandbox) local getImageName = portalModule._image local checkPortals = portalModule._checkPortals local processPortalArgs = portalModule._processPortalArgs local yesno = require( 'Module:Yesno' ) local getArgs = require('Module:Arguments').getArgs local p = {} local function sandboxVersion(s) return isSandbox and s.."-sand" or s end -- Builds the portal bar used by {{portal bar}}. function p._main( portals, args ) -- check for sensible args args = type(args) == "table" and args or {} -- Normalize arguments for key, default in pairs({border=true,redlinks=false,tracking=true}) do if args[key] == nil then args[key] = default end args[key] = yesno(args[key], default) end local nav = mw.html.create( 'div' ) :addClass(sandboxVersion('portal-bar')) :addClass( 'noprint metadata noviewer' ) :attr( 'role', 'navigation' ) :attr( 'aria-label' , 'Portals' ) :addClass(sandboxVersion(args.border and 'portal-bar-bordered' or 'portal-bar-unbordered')) local trackingCat = '' -- Allow any number of portals args.minPortals = 0 args.maxPortals = -1 -- Check to see whether there are redlinks, filter out unless args.redlink is true portals, trackingCat = checkPortals(portals, args) nav:wikitext(trackingCat) if #portals == 0 then return trackingCat end local related = yesno(args.related) if related then nav:addClass(sandboxVersion('portal-bar-related')) else local header = nav:tag('span') header:addClass(sandboxVersion('portal-bar-header')) header:wikitext('[[Wikipedia:Contents/Portals|Portal]]') if #portals > 1 then header:wikitext('s') end header:wikitext(':') end local container = nav:tag('div') container:addClass(sandboxVersion('portal-bar-content')) if related then container:addClass(sandboxVersion('portal-bar-content-related')) end local size = related and '27x25px' or '21x19px' for _, portal in ipairs( portals ) do container :tag( 'span' ) :addClass(sandboxVersion('portal-bar-item')) :wikitext( string.format('[[File:%s|%s]]&nbsp;[[Portal:%s|%s]]', getImageName(portal,true), size, portal, portal)) end local styleFile = 'Module:Portal bar'..sandbox..'/styles.css' return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = styleFile } } .. tostring( nav ) end -- Processes external arguments and sends them to the other functions. function p.main( frame ) local origArgs = getArgs(frame) local portals, args = processPortalArgs(origArgs) return p._main( portals, args ) end return p bb586a960cb56daaef2c7b7c994afbbd94772bbd Module:Portal bar/styles.css 828 119 254 253 2022-09-04T15:25:04Z SpaceMan 2 1 revision imported: Canopus text text/plain /* {{pp|small=y}} */ .portal-bar { font-size: 88%; font-weight: bold; display:flex; justify-content: center; align-items: baseline; } .portal-bar-bordered { padding: 0 2em; background-color: #fdfdfd; border: 1px solid #a2a9b1; clear: both; margin: 1em auto 0; } .portal-bar-related { font-size: 100%; justify-content: flex-start; } .portal-bar-unbordered { padding: 0 1.7em; margin-left: 0; } .portal-bar-header { margin: 0 1em 0 0.5em; flex: 0 0 auto; min-height: 24px; } .portal-bar-content { display:flex; flex-flow: row wrap; flex:0 1 auto; padding: 0.15em 0; column-gap: 1em; align-items: baseline; } .portal-bar-content-related { } .portal-bar-item { display:inline-block; margin:0.15em 0.2em; min-height:24px; line-height:24px; } @media screen and (max-width:768px) { .portal-bar { font-size: 88%; font-weight: bold; display:flex; flex-flow: column wrap; align-items: baseline; } .portal-bar-header { text-align: center; flex:0; padding-left: 0.5em; margin: 0 auto; } .portal-bar-related { font-size: 100%; align-items: flex-start; } .portal-bar-content { display:flex; flex-flow: row wrap; align-items: center; flex:0; column-gap: 1em; border-top: 1px solid #a2a9b1; margin: 0 auto; } .portal-bar-content-related { border-top: none; margin: 0; } } /* .navbox + .portal-bar-bordered */ .navbox + link + .portal-bar-bordered { margin-top: -1px; } .navbox + style + .portal-bar-bordered { margin-top: -1px; } .portal-bar + .navbox-styles + .navbox{ margin-top: -1px; } ec6e77726e7d76d00d66cefce85c3e7d2006d3c5 Template:Trim 10 120 256 255 2022-09-04T15:25:04Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{safesubst:#if:1|{{{x|{{{1|}}}}}}}}</includeonly><noinclude> {{Documentation}} </noinclude> 09ba1a40d9fd41a44a407b144f69a579502fe563 Template:Portal bar 10 121 258 257 2022-09-04T15:25:05Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#invoke:Portal bar|main}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> 147fd2e53f15534b497d1049a4ea239049ec8fbc Module:Portal/images/aliases 828 122 260 259 2022-09-04T15:25:05Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[==[ This is the "aliases" list of portal image names. It contains a list of portal image aliases for use with [[Module:Portal]]. -- The aliases can be used to point to an existing portal image entry. For portals who do not yet have a portal image entry, please -- use the appropriate page from the following list instead: -- [[Module:Portal/images/a]] - for portal names beginning with "A". -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/o]] - for portal names beginning with "O". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/s]] - for portal names beginning with "S". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- When adding entries, please use alphabetical order. The format of the alias table entries is as follows: -- ["portal name"] = {"alias 1", "alias 2", "alias 3"}, -- Both the portal name and the alias names should be in lower case, and the "Portal:" namespace prefix -- should be omitted. For example, if you wanted "UK" to be an alias for "Portal:United Kingdom", then the -- alias name would be "uk" and the portal name would be "united kingdom". ]==] return { ["1990s"] = {"1990's"}, ["2000s"] = {"2000's"}, ["ac/dc"] = {"ac dc"}, ["academy award"] = {"academy awards"}, ["african american"] = {"african-american", "african-americans", "african americans"}, ["african union"] = {"au"}, ["agriculture and agronomy"] = {"agriculture"}, ["american civil war"] = {"acw"}, ["american revolutionary war"] = {"american revolution"}, ["amphibians"] = {"amphibian"}, ["aviation"] = {"airplanes"}, ["åland"] = {"åland islands", "aland islands", "aland", "ax", "ala"}, ["albania"] = {"albanian", "al", "alb"}, ["american football"] = {"college football", "arena football league"}, ["android (operating system)"] = {"android", "android os"}, ["apple inc."] = {"apple", "apple inc"}, ["arabic language"] = {"arabic"}, ["archaeology"] = {"archeology"}, ["asian americans"] = {"asian american"}, ["association football"] = {"soccer"}, ["assyrians"] = {"assyria"}, ["atlas"] = {"cartography"}, ["atmospheric science"] = {"atmosphere","atmospheric sciences"}, ["australia"] = {"australian", "aus"}, ["australian capital territory"] = {"canberra"}, ["banks"] = {"bank", "banking"}, ["baseball"] = {"college baseball", "little league"}, ["basketball"] = {"national basketball league of canada", "wnba"}, ["biography"] = {"people", "biographies"}, ["birds"] = {"bird"}, ["björk"] = {"bjork"}, ["books"] = {"book"}, ["brunei"] = {"brunei darussalam", "bn", "brn"}, ["business and economics"] = {"advertising", "business", "economics", "economy", "marketing"}, ["buses"] = {"bus"}, ["california roads"] = {"roads in california"}, ["california state polytechnic university, pomona"] = {"cal poly pomona"}, ["canada"] = {"canadian", "ca", "can"}, ["canadian armed forces"] = {"canadian forces", "military history of canada"}, ["canary islands"] = {"spanish africa"}, ["caribbean"] = {"caribbean sea", "west indies"}, ["cars"] = {"car", "automobile"}, ["cartoon"] = {"cartoons"}, ["catalan-speaking countries"] = {"catalan", "catalonia"}, ["cats"] = {"cat"}, ["celtic studies"] = {"celts"}, ["children's literature"] = {"children's and young adult literature", "children and young adult literature"}, ["china"] = {"chinese", "cn", "chn"}, ["christiantiy"] = {"christ", "christian"}, ["christianity in india"] = {"indian christianity"}, ["classical civilisation"] = {"classical civilization", "classics"}, ["cleveland"] = {"cleveland, ohio"}, ["coconuts"] = {"coconut"}, ["color"] = {"colour"}, ["comedy"] = {"humour", "humor"}, ["commonwealth realms"] = {"commonwealth"}, ["compact disc"] = {"cd", "compact disk"}, ["companies"] = {"company"}, ["computer-generated imagery"] = {"computer generated imagery"}, ["computer programming"] = {"programming"}, ["county kilkenny"] = {"kilkenny"}, ["criminal justice"] = {"crime"}, ["current events"] = {"events"}, ["czech republic"] = {"czechia", "czech"}, ["dallas – fort worth metroplex"] = {"dallas", "dallas-fort worth", "dallas - fort worth metroplex"}, ["democratic republic of the congo"] = {"zaire", "zaïre", "cod", "drc", "the democratic republic of the congo"}, ["denmark"] = {"kingdom of denmark", "danish", "dk", "dnk"}, ["disasters"] = {"disaster"}, ["dravidian languages"] = {"dravidian", "dravidia", "dravidian peoples", "dravidian civilization"}, ["dominican republic"] = {"the dominican republic"}, ["durham, north carolina"] = {"durham nc"}, ["dungeons & dragons"] = {"d&d"}, ["east timor"] = {"timor leste", "tl"}, ["electromagnetism"] = {"em"}, ["english football"] = {"football in england"}, ["english language"] = {"english"}, ["erotica and pornography"] = {"porn", "pornography"}, ["european military history"] = {"military history of europe"}, ["european union"] = {"eu"}, ["evolutionary biology"] = {"evolution"}, ["extinct and endangered species"] = {"extinction", "endangered species"}, ["falkland islands"] = {"falkland", "malvinas", "fk", "flk"}, ["faroe islands"] = {"the faroe islands"}, ["federated states of micronesia"] = {"fm", "fsm"}, ["film"] = {"films"}, ["football"] = {"association football", "soccer", "soccer ball"}, ["formula one"] = {"f1", "formula 1"}, ["free and open-source software"] = {"free and open source software", "free software", "foss", "open source software", "open-source software", "oss"}, ["freedom of speech"] = {"censorship", "free speech"}, ["french and francophone literature"] = {"french literature"}, ["french politics"] = {"politics of france"}, ["gardening"] = {"gardening and horticulture"}, ["gemology and jewelry"] = {"gemmology and jewellery", "gemmology and jewelry", "gemology and jewellery"}, ["georgia (country)"] = {"georgia", "republic of georgia", "ge", "geo"}, ["georgia (u.s. state)"] = {"georgia (state)"}, ["globalization"] = {"globalisation"}, ["gullah"] = {"gullah people"}, ["hawaii"] = {"hawai'i", "hawaiʻi", "us-hi"}, ["hazardous materials"] = {"dangerous goods"}, ["health and fitness"] = {"health"}, ["himalayas"] = {"himalaya region"}, ["hindustani"] = {"hindustani language", "hindustani and allied languages"}, ["hip hop"] = {"hip-hop"}, ["hispanic and latino americans"] = {"hispanic and latino american", "latino and hispanic americans", "latino and hispanic american"}, ["horror fiction"] = {"horror"}, ["horticulture and gardening"] = {"horticulture"}, ["hunger relief"] = {"hunger"}, ["india"] = {"indian", "in", "ind", "republic of india"}, ["indian women"] = {"women of india", "indian women and gender issues"}, ["indiana"] = {"hoosier", "us-in"}, ["indigenous peoples of north america"] = {"indigenous people of north america"}, ["information technology"] = {"computing", "computer science", "it"}, ["insects"] = {"insect"}, ["ireland"] = {"irish"}, ["islam"] = {"muslim history"}, ["islamic state of iraq and the levant"] = {"daesh", "isil", "isis"}, ["islands"] = {"island"}, ["italy"] = {"italian", "ita"}, ["jacksonville, florida"] = {"jacksonville"}, ["kazi nazrul islam"] = {"nazrul"}, ["latter day saint movement"] = {"lds"}, ["lemony snicket"] = {"a series of unfortunate events"}, ["lgbt"] = {"lgbtq", "lgbtqa"}, ["library and information science"] = {"information science"}, ["madonna (entertainer)"] = {"madonna"}, ["mediterranean"] = {"mediterranean sea"}, ["metro detroit"] = {"detroit"}, ["mexico"] = {"méxico", "mx", "mex"}, ["middle tennessee state university"] = {"mtsu"}, ["michigan highways"] = {"highways in michigan"}, ["molecular and cell biology"] = {"molecular and cellular biology"}, ["moldova"] = {"republic of moldova"}, ["mongolia"] = {"mongols"}, ["mountains"] = {"mountain"}, ["music of australia"] = {"australian music"}, ["myanmar"] = {"burma", "burmese", "mm", "mmr"}, ["national register of historic places"] = {"nrhp"}, ["nazism"] = {"nazi germany"}, ["netherlands"] = {"kingdom of the netherlands", "nl", 'nld', 'caribbean netherlands', 'the netherlands', 'dutch empire', 'the dutch empire'}, ["new york"] = {"new york state", "new york (state)", "us-ny"}, ["new york city"] = {"nyc"}, ["new zealand"] = {"nz", "nzl"}, ["north korea"] = {"dprk", "democratic people's republic of korea"}, ["north macedonia"] = {"republic of north macedonia", "mk", "mkd"}, ["north rhine-westphalia"] = {"nrw"}, ["oceans"] = {"ocean", "world ocean"}, ["odisha"] = {"orissa"}, ["opera"] = {"operas"}, ["organized labour"] = {"organised labour", "organized labor"}, ["pakistan"] = {"pakistani", "pk", "pak"}, ["paleontology"] = {"palaeontology"}, ["palestine"] = {"the state of palestine","state of palestine"}, ["paralympic games"] = {"paralympics"}, ["pan-africanism"] = {"pan-african"}, ["people's republic of china"] = {"prc"}, ["pharmacy and pharmacology"] = {"pharmacy"}, ["pitcairn islands"] = {"pitcairn, henderson, ducie and oeno islands"}, ["politics"] = {"government"}, ["prince edward island"] = {"pei", "ca-pe"}, ["protected areas of india"] = {"biodiversity, protected areas & environment of india", "biodiversity of india", "environment of india"}, ["puducherry"] = {"pondicherry", "in-py"}, ["punjab, india"] = {"punjab (india)", "in-pb"}, ["punjab, pakistan"] = {"punjab (pakistan)", "western punjab", "pk-pb"}, ["python programming"] = {"python"}, ["quebec"] = {"québec", "ca-qc"}, ["religion"] = {"religions"}, ["republic of ireland"] = {"éire", "ie", "irl", "irish republicanism"}, ["republic of north macedonia"] = {"north macedonia", "mk", "mkd", "the republic of macedonia", "republic of macedonia"}, ["republic of the congo"] = {"the republic of the congo", "republic of congo", "french congo"}, ["roads of canada"] = {"canada roads"}, ["romani people"] = {"roma", "romani"}, ["saint barthelemy"] = {"saint-barthélemy", "saint barthélemy"}, ["saint helena, ascension and tristan da cunha"] = {"saint helena"}, ["salad dressing"] = {"salad dressings"}, ["sandwich"] = {"sandwiches"}, ["schools"] = {"school"}, ["serer people"] = {"serer"}, ["september 11 attacks"] = {"september 11, 2001"}, ["sexuality"] = {"sex"}, ["soap operas and telenovelas"] = {"soap operas", "telenovelas"}, ["south africa"] = {"za", "zaf"}, ["south georgia and the south sandwich islands"] = {"south georgia", "south sandwich islands", "gs", "sgs"}, ["soviet union"] = {"ussr"}, ["space"] = {"outer space"}, ["spices"] = {"herbs and spices"}, ["sports in canada"] = {"canadian sports", "canadian sport", "sports of canada", "sport in canada"}, ["sports"] = {"sport"}, ["st. john's, newfoundland and labrador"] = {"st. john's"}, ["state of georgia"] = {"georgia (u.s. state)", "georgia usa", "us-ga"}, ["state of mexico"] = {"mexico (state)", "mx-mex"}, ["state university of new york"] = {"suny"}, ["taiwan"] = {"republic of china", "roc", "tw", "twn"}, ["tamil people"] = {"tamil"}, ["tanks"] = {"tank"}, ["telecommunication"] = {"telecommunications", "telecoms", "telecomms", "telecomm", "telecom"}, ["texas a&m university"] = {"texas a&m"}, ["texas tech university"] = {"texas tech"}, ["theatre"] = {"theater"}, ["the bahamas"] = {"bahamas", "bs", "bhs"}, ["the gambia"] = {"gambia", "gm", "gmb"}, ["the legend of zelda"] = {"legend of zelda"}, ["tiruchirappalli"] = {"trichy", "tiruchi"}, ["transportation"] = {"transport"}, ["trauma and orthopaedics"] = {"trauma & orthopaedics"}, ["tropical cyclones"] = {"tropical cyclone"}, ["united arab emirates"] = {"emirates", "ae", "uae", "emirati"}, ["united kingdom"] = {"the united kingdom", "uk", "gb", "gbr", "british", "british overseas territories"}, ["united nations"] = {"un"}, ["united states"] = {"us", "usa", "u.s.", "united states armed forces", "american", "territories of the united states"}, ["united states arms"] = {"united states armed forces", "united states military", "united states military history", "u.s. armed forces", "u.s. military"}, ["united states congress"] = {"u.s. congress"}, ["united states counties"] = {"u.s. counties"}, ["united states presidents"] = {"u.s. presidents"}, ["united states roads"] = {"u.s. roads"}, ["united states state legislatures"] = {"u.s. state legislatures", "us state legislatures"}, ["united states streets"] = {"u.s. streets"}, ["united states supreme court"] = {"u.s. supreme court cases"}, ["united states territories"] = {"territories of the united states"}, ["university of missouri"] = {"mizzou"}, ["university of notre dame"] = {"notre dame"}, ["university of pittsburgh"] = {"pitt"}, ["video games"] = {"vg", "video game"}, ["war"] = {"military"}, ["washington (state)"] = {"washington", "us-wa"}, ["washington, d.c."] = {"district of columbia", "dc", "washington dc", "us-dc"}, ["western asia"] = {"west asia"}, ["western sahara"] = {"sahrawi arab democratic republic", "eh", "esh"}, ["world war i"] = {"first world war"}, ["world war ii"] = {"second world war"}, ["zoos"] = {"zoo"} } 06ad5a8008671463b8305eb44bb61afb68f4f1df Template:Comma separated entries 10 123 262 261 2022-09-04T15:25:05Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{<includeonly>safesubst:</includeonly>#invoke:Separated entries|comma}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> f9811ed089bab742e4aad8b8463eddcc7607f062 Template:Citation 10 124 264 263 2022-09-04T15:25:06Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=citation }}</includeonly><noinclude> {{Documentation}} </noinclude> 682134a60c143dec260ce779777d3be2d4c94eaa Module:Template wrapper 828 125 266 265 2022-09-04T15:25:06Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain require('Module:No globals'); local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; --[[--------------------------< I S _ I N _ T A B L E >-------------------------------------------------------- scan through tbl looking for value; return true if found, false else ]] local function is_in_table (tbl, value) for k, v in pairs (tbl) do if v == value then return true end end return false; end --[[--------------------------< A D D _ P A R A M E T E R >---------------------------------------------------- adds parameter name and its value to args table according to the state of boolean list argument; kv pair for template execution; k=v string for template listing. ]] local function add_parameter (k, v, args, list) if list then table.insert( args, table.concat ({k, '=', v})); -- write parameter names and values to args table as string else args[k] = v; -- copy parameters to args table end end --[[--------------------------< A L I A S _ M A P _ G E T >---------------------------------------------------- returns a table of local template (parent frame) parameter names and the target template names that match where in [key]=<value> pairs where: [key] is local template parameter name (an alias) <value> is target template parameter name (the canonical parameter name used in the working template) The parameter |_alias-map= has the form: |_alias-map=<list> where <list> is a comma-separated list of alias / canonical parameter name pairs in the form <from> : <to> where: <from> is the local template's parameter name (alias) <to> is the target template's parameter name (canonical) for enumerated parameters place an octothorp (#) where the enumerator digits are placed in the parameter names: <from#> : <to#> ]] local function alias_map_get (_alias_map) local T = mw.text.split (_alias_map, '%s*,%s*'); -- convert the comma-separated list into a table of alias pairs local mapped_aliases = {}; -- mapped aliases will go here local l_name, t_name; -- parameter names for _, alias_pair in ipairs (T) do -- loop through the table of alias pairs l_name, t_name = alias_pair:match ('(.-)%s*:%s*(.+)'); -- from each pair, get local and target parameter names if l_name and t_name then -- if both are set if tonumber (l_name) then l_name = tonumber (l_name); -- convert number-as-text to a number end mapped_aliases[l_name] = t_name; -- add them to the map table end end return mapped_aliases; end --[[--------------------------< F R A M E _ A R G S _ G E T >-------------------------------------------------- Fetch the wrapper template's 'default' and control parameters; adds default parameters to args returns content of |_template= parameter (name of the working template); nil else ]] local function frame_args_get (frame_args, args, list) local template; for k, v in pairs (frame_args) do -- here we get the wrapper template's 'default' parameters if 'string' == type (k) and (v and ('' ~= v)) then -- do not pass along positional or empty parameters if '_template' == k then template = v; -- save the name of template that we are wrapping elseif '_exclude' ~= k and '_reuse' ~= k and '_include-positional' ~= k and '_alias-map' ~= k then -- these already handled so ignore here; add_parameter (k, v, args, list); -- add all other parameters to args in the style dictated by list end end end return template; -- return contents of |_template= parameter end --[=[--------------------------< P F R A M E _ A R G S _ G E T >------------------------------------------------ Fetches the wrapper template's 'live' parameters; adds live parameters that aren't members of the exclude table to args table; positional parameters may not be excluded no return value ]=] local function pframe_args_get (pframe_args, args, exclude, _include_positional, list) for k, v in pairs (pframe_args) do if 'string' == type (k) and not is_in_table (exclude, k) then -- do not pass along excluded parameters if v and ('' ~= v) then -- pass along only those parameters that have assigned values if 'unset' == v:lower() then -- special keyword to unset 'default' parameters set in the wrapper template v = ''; -- unset the value in the args table end add_parameter (k, v, args, list) -- add all other parameters to args in the style dictated by list; alias map only supported for local-template parameters end end end if _include_positional then for i, v in ipairs (pframe_args) do -- pass along positional parameters if 'unset' == v:lower() then -- special keyword to unset 'default' parameters set in the wrapper template v = ''; -- unset the value in the args table end add_parameter (i, v, args, list); end end end --[[--------------------------< _ M A I N >-------------------------------------------------------------------- Collect the various default and live parameters into args styled according to boolean list. returns name of the working or listed template or nil for an error message ]] local function _main (frame, args, list) local template; local exclude = {}; -- table of parameter names for parameters that are not passed to the working template local reuse_list = {}; -- table of pframe parameter names whose values are modified before they are passed to the working template as the same name local alias_map = {}; -- table that maps parameter aliases to working template canonical parameter names local _include_positional; if frame.args._exclude and ('' ~= frame.args._exclude) then -- if there is |_exclude= and it's not empty exclude = mw.text.split (frame.args._exclude, "%s*,%s*"); -- make a table from its contents end -- TODO: |_reuse= needs a better name (|_reuse=) if frame.args._reuse and ('' ~= frame.args._reuse) then -- if there is |_reuse= and it's not empty reuse_list = mw.text.split (frame.args._reuse, "%s*,%s*"); -- make a table from its contents end if frame.args['_alias-map'] and ('' ~= frame.args['_alias-map']) then -- if there is |_alias-map= and it's not empty alias_map = alias_map_get (frame.args['_alias-map']); -- make a table from its contents end template = frame_args_get (frame.args, args, list); -- get parameters provided in the {{#invoke:template wrapper|...|...}} if nil == template or '' == template then -- this is the one parameter that is required by this module return nil; -- not present, tell calling function to emit an error message end _include_positional = 'yes' == frame.args['_include-positional']; -- when true pass all positional parameters along with non-excluded named parameters to ... -- ... the working template; positional parameters are not excludable local _pframe_args = frame:getParent().args; -- here we get the wrapper template's 'live' parameters from pframe.args local pframe_args = {}; -- a local table that we can modify for k, v in pairs (_pframe_args) do -- make a copy that we can modify pframe_args[k] = v; end -- here we look for pframe parameters that are aliases of canonical parameter names; when found -- we replace the alias with the canonical. We do this here because the reuse_list works on -- canonical parameter names so first we convert alias parameter names to canonical names and then -- we remove those canonical names from the pframe table that are reused (provided to the working -- template through the frame args table) for k, v in pairs (alias_map) do -- k is alias name, v is canonical name if pframe_args[k] then -- if pframe_args has parameter with alias name pframe_args[v] = _pframe_args[k]; -- create new canonical name with alias' value pframe_args[k] = nil; -- unset the alias end end for k, v in pairs (pframe_args) do -- do enumerated parameter alias -> canonical translation if 'string' == type (k) then -- only named parameters can be enumerated if alias_map[k..'#'] then -- non-enumerated alias matches enumerated parameter pattern? enumerator at end only pframe_args[alias_map[k..'#']:gsub('#', '')] = v; -- remove '#' and copy parameter to pframe_args table pframe_args[k] = nil; -- unset the alias elseif k:match ('%d+') then -- if this parameter name contains digits local temp = k:gsub ('%d+', '#'); -- make a copy; digits replaced with single '#' local enum = k:match ('%d+'); -- get the enumerator if alias_map[temp] then -- if this parameter is a recognized enumerated alias pframe_args[alias_map[temp]:gsub('#', enum)] = v; -- use canonical name and replace '#' with enumerator and add to pframe_args pframe_args[k] = nil; -- unset the alias end end end end -- pframe parameters that are _reused are 'reused' have the form something like this: -- |chapter=[[wikisource:{{{chapter}}}|{{{chapter}}}]] -- where a parameter in the wrapping template is modified and then passed to the working template -- using the same parameter name (in this example |chapter=) -- remove parameters that will be reused for k, v in ipairs (reuse_list) do -- k is numerical index, v is canonical parameter name to ignore if pframe_args[v] then -- if pframe_args has parameter that should be ignored pframe_args[v] = nil; -- unset the ignored parameter end end pframe_args_get (pframe_args, args, exclude, _include_positional, list); -- add parameters and values to args that are not listed in the exclude table return template; -- args now has all default and live parameters, return working template name end --[[--------------------------< W R A P >---------------------------------------------------------------------- Template entry point. Call this function to 'execute' the working template ]] local function wrap (frame) local args = {}; -- table of default and live parameters and their values to be passed to the wrapped template local template; -- the name of the working template template = _main (frame, args, false); -- get default and live parameters and the name of the working template if not template then -- template name is required return error_msg; -- emit error message and abandon if template name not present end return frame:expandTemplate {title=template, args=args}; -- render the working template end --[[--------------------------< L I S T >---------------------------------------------------------------------- Template entry point. Call this function to 'display' the source for the working template. This function added as a result of a TfD here: Wikipedia:Templates_for_discussion/Log/2018_April_28#Module:PassArguments This function replaces a similarly named function which was used in {{cite compare}} and {{cite compare2}} Values in the args table are numerically indexed strings in the form 'name=value' ]] local function list(frame, do_link) local args = {}; -- table of default and live parameters and their values to be passed to the listed template local template; -- the name of the listed template template = _main (frame, args, true); -- get default and live parameters and the name of the listed template if not template then -- template name is required return error_msg; -- emit error message and abandon if template name not present end if do_link then template = ('[[%s|%s]]'):format(frame:expandTemplate{ title='Transclude', args = {template} }, template) end table.sort(args) for i = 1, #args do local stripped = args[i]:match('^' .. i .. '=([^=]*)$') if stripped then args[i] = stripped else break end end return frame:preprocess(table.concat({ '<code style="color:inherit; background:inherit; border:none;">&#123;&#123;', template, ('<wbr><nowiki>|%s</nowiki>'):rep(#args):format(unpack(args)), '&#125;&#125;</code>'})); -- render the template end local function link (frame) return list(frame, true) end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return { link = link, list = list, wrap = wrap, }; aa1b56cac4081642637ea7d11fba53513d4335a7 Template:Round 10 126 268 267 2022-09-04T15:25:06Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{safesubst<noinclude/>:#iferror:{{#expr:{{{2|0}}}}} | {{main other|[[Category:Pages with bad rounding precision]]}}{{hid|Bad rounding here}}<!-- -->{{safesubst<noinclude/>:#invoke:Math|precision_format| {{{1}}} | 1-{{order of magnitude|{{{1}}}}} }}| {{safesubst<noinclude/>:#invoke:Math|precision_format| {{{1}}} | {{{2|0}}}}}}}</includeonly><noinclude> {{documentation}} </noinclude> 9c2874586b74824fe1beb6830b56eabe7ad936ce Module:Math 828 127 270 269 2022-09-04T15:25:07Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[[ This module provides a number of basic mathematical operations. ]] local yesno, getArgs -- lazily initialized local p = {} -- Holds functions to be returned from #invoke, and functions to make available to other Lua modules. local wrap = {} -- Holds wrapper functions that process arguments from #invoke. These act as intemediary between functions meant for #invoke and functions meant for Lua. --[[ Helper functions used to avoid redundant code. ]] local function err(msg) -- Generates wikitext error messages. return mw.ustring.format('<strong class="error">Formatting error: %s</strong>', msg) end local function unpackNumberArgs(args) -- Returns an unpacked list of arguments specified with numerical keys. local ret = {} for k, v in pairs(args) do if type(k) == 'number' then table.insert(ret, v) end end return unpack(ret) end local function makeArgArray(...) -- Makes an array of arguments from a list of arguments that might include nils. local args = {...} -- Table of arguments. It might contain nils or non-number values, so we can't use ipairs. local nums = {} -- Stores the numbers of valid numerical arguments. local ret = {} for k, v in pairs(args) do v = p._cleanNumber(v) if v then nums[#nums + 1] = k args[k] = v end end table.sort(nums) for i, num in ipairs(nums) do ret[#ret + 1] = args[num] end return ret end local function fold(func, ...) -- Use a function on all supplied arguments, and return the result. The function must accept two numbers as parameters, -- and must return a number as an output. This number is then supplied as input to the next function call. local vals = makeArgArray(...) local count = #vals -- The number of valid arguments if count == 0 then return -- Exit if we have no valid args, otherwise removing the first arg would cause an error. nil, 0 end local ret = table.remove(vals, 1) for _, val in ipairs(vals) do ret = func(ret, val) end return ret, count end --[[ Fold arguments by selectively choosing values (func should return when to choose the current "dominant" value). ]] local function binary_fold(func, ...) local value = fold((function(a, b) if func(a, b) then return a else return b end end), ...) return value end --[[ random Generate a random number Usage: {{#invoke: Math | random }} {{#invoke: Math | random | maximum value }} {{#invoke: Math | random | minimum value | maximum value }} ]] function wrap.random(args) local first = p._cleanNumber(args[1]) local second = p._cleanNumber(args[2]) return p._random(first, second) end function p._random(first, second) math.randomseed(mw.site.stats.edits + mw.site.stats.pages + os.time() + math.floor(os.clock() * 1000000000)) -- math.random will throw an error if given an explicit nil parameter, so we need to use if statements to check the params. if first and second then if first <= second then -- math.random doesn't allow the first number to be greater than the second. return math.random(first, second) end elseif first then return math.random(first) else return math.random() end end --[[ order Determine order of magnitude of a number Usage: {{#invoke: Math | order | value }} ]] function wrap.order(args) local input_string = (args[1] or args.x or '0'); local input_number = p._cleanNumber(input_string); if input_number == nil then return err('order of magnitude input appears non-numeric') else return p._order(input_number) end end function p._order(x) if x == 0 then return 0 end return math.floor(math.log10(math.abs(x))) end --[[ precision Detemines the precision of a number using the string representation Usage: {{ #invoke: Math | precision | value }} ]] function wrap.precision(args) local input_string = (args[1] or args.x or '0'); local trap_fraction = args.check_fraction; local input_number; if not yesno then yesno = require('Module:Yesno') end if yesno(trap_fraction, true) then -- Returns true for all input except nil, false, "no", "n", "0" and a few others. See [[Module:Yesno]]. local pos = string.find(input_string, '/', 1, true); if pos ~= nil then if string.find(input_string, '/', pos + 1, true) == nil then local denominator = string.sub(input_string, pos+1, -1); local denom_value = tonumber(denominator); if denom_value ~= nil then return math.log10(denom_value); end end end end input_number, input_string = p._cleanNumber(input_string); if input_string == nil then return err('precision input appears non-numeric') else return p._precision(input_string) end end function p._precision(x) if type(x) == 'number' then x = tostring(x) end x = string.upper(x) local decimal = x:find('%.') local exponent_pos = x:find('E') local result = 0; if exponent_pos ~= nil then local exponent = string.sub(x, exponent_pos + 1) x = string.sub(x, 1, exponent_pos - 1) result = result - tonumber(exponent) end if decimal ~= nil then result = result + string.len(x) - decimal return result end local pos = string.len(x); while x:byte(pos) == string.byte('0') do pos = pos - 1 result = result - 1 if pos <= 0 then return 0 end end return result end --[[ max Finds the maximum argument Usage: {{#invoke:Math| max | value1 | value2 | ... }} Note, any values that do not evaluate to numbers are ignored. ]] function wrap.max(args) return p._max(unpackNumberArgs(args)) end function p._max(...) local max_value = binary_fold((function(a, b) return a > b end), ...) if max_value then return max_value end end --[[ median Find the median of set of numbers Usage: {{#invoke:Math | median | number1 | number2 | ...}} OR {{#invoke:Math | median }} ]] function wrap.median(args) return p._median(unpackNumberArgs(args)) end function p._median(...) local vals = makeArgArray(...) local count = #vals table.sort(vals) if count == 0 then return 0 end if p._mod(count, 2) == 0 then return (vals[count/2] + vals[count/2+1])/2 else return vals[math.ceil(count/2)] end end --[[ min Finds the minimum argument Usage: {{#invoke:Math| min | value1 | value2 | ... }} OR {{#invoke:Math| min }} When used with no arguments, it takes its input from the parent frame. Note, any values that do not evaluate to numbers are ignored. ]] function wrap.min(args) return p._min(unpackNumberArgs(args)) end function p._min(...) local min_value = binary_fold((function(a, b) return a < b end), ...) if min_value then return min_value end end --[[ sum Finds the sum Usage: {{#invoke:Math| sum | value1 | value2 | ... }} OR {{#invoke:Math| sum }} Note, any values that do not evaluate to numbers are ignored. ]] function wrap.sum(args) return p._sum(unpackNumberArgs(args)) end function p._sum(...) local sums, count = fold((function(a, b) return a + b end), ...) if not sums then return 0 else return sums end end --[[ average Finds the average Usage: {{#invoke:Math| average | value1 | value2 | ... }} OR {{#invoke:Math| average }} Note, any values that do not evaluate to numbers are ignored. ]] function wrap.average(args) return p._average(unpackNumberArgs(args)) end function p._average(...) local sum, count = fold((function(a, b) return a + b end), ...) if not sum then return 0 else return sum / count end end --[[ round Rounds a number to specified precision Usage: {{#invoke:Math | round | value | precision }} --]] function wrap.round(args) local value = p._cleanNumber(args[1] or args.value or 0) local precision = p._cleanNumber(args[2] or args.precision or 0) if value == nil or precision == nil then return err('round input appears non-numeric') else return p._round(value, precision) end end function p._round(value, precision) local rescale = math.pow(10, precision or 0); return math.floor(value * rescale + 0.5) / rescale; end --[[ log10 returns the log (base 10) of a number Usage: {{#invoke:Math | log10 | x }} ]] function wrap.log10(args) return math.log10(args[1]) end --[[ mod Implements the modulo operator Usage: {{#invoke:Math | mod | x | y }} --]] function wrap.mod(args) local x = p._cleanNumber(args[1]) local y = p._cleanNumber(args[2]) if not x then return err('first argument to mod appears non-numeric') elseif not y then return err('second argument to mod appears non-numeric') else return p._mod(x, y) end end function p._mod(x, y) local ret = x % y if not (0 <= ret and ret < y) then ret = 0 end return ret end --[[ gcd Calculates the greatest common divisor of multiple numbers Usage: {{#invoke:Math | gcd | value 1 | value 2 | value 3 | ... }} --]] function wrap.gcd(args) return p._gcd(unpackNumberArgs(args)) end function p._gcd(...) local function findGcd(a, b) local r = b local oldr = a while r ~= 0 do local quotient = math.floor(oldr / r) oldr, r = r, oldr - quotient * r end if oldr < 0 then oldr = oldr * -1 end return oldr end local result, count = fold(findGcd, ...) return result end --[[ precision_format Rounds a number to the specified precision and formats according to rules originally used for {{template:Rnd}}. Output is a string. Usage: {{#invoke: Math | precision_format | number | precision }} ]] function wrap.precision_format(args) local value_string = args[1] or 0 local precision = args[2] or 0 return p._precision_format(value_string, precision) end function p._precision_format(value_string, precision) -- For access to Mediawiki built-in formatter. local lang = mw.getContentLanguage(); local value value, value_string = p._cleanNumber(value_string) precision = p._cleanNumber(precision) -- Check for non-numeric input if value == nil or precision == nil then return err('invalid input when rounding') end local current_precision = p._precision(value) local order = p._order(value) -- Due to round-off effects it is neccesary to limit the returned precision under -- some circumstances because the terminal digits will be inaccurately reported. if order + precision >= 14 then if order + p._precision(value_string) >= 14 then precision = 13 - order; end end -- If rounding off, truncate extra digits if precision < current_precision then value = p._round(value, precision) current_precision = p._precision(value) end local formatted_num = lang:formatNum(math.abs(value)) local sign -- Use proper unary minus sign rather than ASCII default if value < 0 then sign = '−' else sign = '' end -- Handle cases requiring scientific notation if string.find(formatted_num, 'E', 1, true) ~= nil or math.abs(order) >= 9 then value = value * math.pow(10, -order) current_precision = current_precision + order precision = precision + order formatted_num = lang:formatNum(math.abs(value)) else order = 0; end formatted_num = sign .. formatted_num -- Pad with zeros, if needed if current_precision < precision then local padding if current_precision <= 0 then if precision > 0 then local zero_sep = lang:formatNum(1.1) formatted_num = formatted_num .. zero_sep:sub(2,2) padding = precision if padding > 20 then padding = 20 end formatted_num = formatted_num .. string.rep('0', padding) end else padding = precision - current_precision if padding > 20 then padding = 20 end formatted_num = formatted_num .. string.rep('0', padding) end end -- Add exponential notation, if necessary. if order ~= 0 then -- Use proper unary minus sign rather than ASCII default if order < 0 then order = '−' .. lang:formatNum(math.abs(order)) else order = lang:formatNum(order) end formatted_num = formatted_num .. '<span style="margin:0 .15em 0 .25em">×</span>10<sup>' .. order .. '</sup>' end return formatted_num end --[[ divide Implements the division operator Usage: {{#invoke:Math | divide | x | y | round= | precision= }} --]] function wrap.divide(args) local x = args[1] local y = args[2] local round = args.round local precision = args.precision if not yesno then yesno = require('Module:Yesno') end return p._divide(x, y, yesno(round), precision) end function p._divide(x, y, round, precision) if y == nil or y == "" then return err("Empty divisor") elseif not tonumber(y) then if type(y) == 'string' and string.sub(y, 1, 1) == '<' then return y else return err("Not a number: " .. y) end elseif x == nil or x == "" then return err("Empty dividend") elseif not tonumber(x) then if type(x) == 'string' and string.sub(x, 1, 1) == '<' then return x else return err("Not a number: " .. x) end else local z = x / y if round then return p._round(z, 0) elseif precision then return p._round(z, precision) else return z end end end --[[ Helper function that interprets the input numerically. If the input does not appear to be a number, attempts evaluating it as a parser functions expression. ]] function p._cleanNumber(number_string) if type(number_string) == 'number' then -- We were passed a number, so we don't need to do any processing. return number_string, tostring(number_string) elseif type(number_string) ~= 'string' or not number_string:find('%S') then -- We were passed a non-string or a blank string, so exit. return nil, nil; end -- Attempt basic conversion local number = tonumber(number_string) -- If failed, attempt to evaluate input as an expression if number == nil then local success, result = pcall(mw.ext.ParserFunctions.expr, number_string) if success then number = tonumber(result) number_string = tostring(number) else number = nil number_string = nil end else number_string = number_string:match("^%s*(.-)%s*$") -- String is valid but may contain padding, clean it. number_string = number_string:match("^%+(.*)$") or number_string -- Trim any leading + signs. if number_string:find('^%-?0[xX]') then -- Number is using 0xnnn notation to indicate base 16; use the number that Lua detected instead. number_string = tostring(number) end end return number, number_string end --[[ Wrapper function that does basic argument processing. This ensures that all functions from #invoke can use either the current frame or the parent frame, and it also trims whitespace for all arguments and removes blank arguments. ]] local mt = { __index = function(t, k) return function(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end return wrap[k](getArgs(frame)) -- Argument processing is left to Module:Arguments. Whitespace is trimmed and blank arguments are removed. end end } return setmetatable(p, mt) 2bbe734d898299f65412963a3c1782e9fcc4d9ca Template:Sclass 10 128 272 271 2022-09-04T15:25:07Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{sclass/core|1={{{1}}}|2={{{2}}}|3={{{3|}}}|4={{{4|}}}|5={{{5|}}}|format=sclass}}</includeonly><!-- --><noinclude>{{documentation}}</noinclude> 9e6cac27c57200a375f9fd66187d590a922157d2 Template:Sclass/core 10 129 274 273 2022-09-04T15:25:07Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>[[{{{1}}}-class {{{2}}} {{#if:{{{5|}}}|({{{5}}})}}|{{#switch:{{{format}}} |sclass =''{{{1}}}'' |sclass2 ={{{1}}} }}<!-- -->{{#switch:{{{3|}}} |=-class]] [[{{#if:{{{4|}}}|{{{2}}} ({{{4}}}){{!}}{{{2}}}|{{{2}}}}}]] |0 =-class]] |1 =-class&#x20;{{{2}}}]] |2 =-class]] {{{2}}} |3 =-class]] [[{{#if:{{{4|}}}|{{{2}}} ({{{4}}}){{!}}{{{2}}}|{{{2}}}}}]] |4 =&#x20;class]] |5 =]] |6|#default=-class&#x20;{{{2}}}]]<!-- same as 1, 3; warning + cat -->{{preview warning|[[Template:{{{format|}}}|Template {{ucfirst:{{{format|}}}}}]], invalid format code: {{{3|}}}. Should be 1&ndash;5, or blank.}}{{main other|[[Category:WPSHIPS: sclass invalid option]]}}<!-- -->}}<!-- eo switch --></includeonly><noinclude>{{documentation}}</noinclude> d536aa9b427477a08e0d51d8dc68ef00c5c82098 Template:Cite OED 10 130 276 275 2022-09-04T15:25:07Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#invoke:template wrapper|{{#if:{{{_debug|}}}|list|wrap}}|_template=cite dictionary |_exclude=id, short, term, _debug |url={{#ifeq:{{{term|{{{1|}}}<!-- -->}}}|<!--not set-->| |{{#if:{{{id|}}} |https://www.oed.com/view/Entry/{{{id}}} |https://oed.com/search?searchType=dictionary&q={{urlencode:{{{term|{{{1|}}}}}}}} }} }} |url-access={{#if:{{{term|}}}{{{1|}}}{{{id|}}}|subscription}} |title={{{term|{{{1|}}}}}} |dictionary=[[Oxford English Dictionary]] |publisher={{#if:{{{short|}}}||[[Oxford University Press]]}} |edition={{#if:{{{short|}}}||Online}} |ref={{#if:{{{term|}}}{{{1|}}}{{{id|}}}|{{SfnRef|Reference-OED-{{{term|{{{1|}}}}}}}}}} }}{{#if:{{{short|}}}| |&nbsp;{{OEDsub|sentence={{#ifeq:{{{mode|cs1}}}|cs1|yes|no}}}}<!---->}}<noinclude> {{documentation}} </noinclude> c4826a4de9a2fb0fb19a568c15f96013d914f71d Template:Cite dictionary 10 131 278 277 2022-09-04T15:25:08Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki #REDIRECT [[Template:Cite encyclopedia]] b08dc3862c41642a1bb23bc31b3764ffdce55dcc Template:Link note 10 132 280 279 2022-09-04T15:25:08Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <span style="font-size:0.95em; font-size:95%; color:#555">({{{note|}}})</span><includeonly>{{#if:{{{cat|}}}|{{DMCA|{{{cat|}}}|from|{{{date|}}}}}}}</includeonly><noinclude>{{documentation}}</noinclude> 86089fa5a81775a10f0a53b58426a73b5c9a69ba Template:OED 10 133 282 281 2022-09-04T15:25:09Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki #REDIRECT [[Template:Cite OED]] {{R from move}} d5391a8c7307b290008c46b310b929153eb9440f Template:OEDsub 10 134 284 283 2022-09-04T15:25:09Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{link note|note={{#ifeq: {{{sentence|no}}} | yes | S | s }}ubscription or [https://www.oed.com/public/login/loggingin#withyourlibrary participating institution membership] required{{#ifeq: {{{sentence|no}}} | yes | . | }}}}<noinclude> {{Documentation}} </noinclude> 66a4cfbe3af90f20ac87af655115d9debd61bb56 Template:Cite conference 10 135 286 285 2022-09-04T15:25:09Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:citation/CS1|citation |CitationClass=conference }}</includeonly><noinclude> {{documentation}} </noinclude> 3c799319c67a4e713f07b5476ef62fa6a9efc608 Module:Portal/images/o 828 136 288 287 2022-09-04T15:25:09Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain --[==[ This is the "O" list of portal image names. It contains a list of portal images for use with [[Module:Portal]] -- for portal names that start with the letter "O". For aliases to existing portal names, and for portal names that -- start with other letters, please use the appropriate page from the following list: -- [[Module:Portal/images/a]] - for portal names beginning with "A". -- [[Module:Portal/images/b]] - for portal names beginning with "B". -- [[Module:Portal/images/c]] - for portal names beginning with "C". -- [[Module:Portal/images/d]] - for portal names beginning with "D". -- [[Module:Portal/images/e]] - for portal names beginning with "E". -- [[Module:Portal/images/f]] - for portal names beginning with "F". -- [[Module:Portal/images/g]] - for portal names beginning with "G". -- [[Module:Portal/images/h]] - for portal names beginning with "H". -- [[Module:Portal/images/i]] - for portal names beginning with "I". -- [[Module:Portal/images/j]] - for portal names beginning with "J". -- [[Module:Portal/images/k]] - for portal names beginning with "K". -- [[Module:Portal/images/l]] - for portal names beginning with "L". -- [[Module:Portal/images/m]] - for portal names beginning with "M". -- [[Module:Portal/images/n]] - for portal names beginning with "N". -- [[Module:Portal/images/p]] - for portal names beginning with "P". -- [[Module:Portal/images/q]] - for portal names beginning with "Q". -- [[Module:Portal/images/r]] - for portal names beginning with "R". -- [[Module:Portal/images/s]] - for portal names beginning with "S". -- [[Module:Portal/images/t]] - for portal names beginning with "T". -- [[Module:Portal/images/u]] - for portal names beginning with "U". -- [[Module:Portal/images/v]] - for portal names beginning with "V". -- [[Module:Portal/images/w]] - for portal names beginning with "W". -- [[Module:Portal/images/x]] - for portal names beginning with "X". -- [[Module:Portal/images/y]] - for portal names beginning with "Y". -- [[Module:Portal/images/z]] - for portal names beginning with "Z". -- [[Module:Portal/images/other]] - for portal names beginning with any other letters. This includes numbers, -- letters with diacritics, and letters in non-Latin alphabets. -- [[Module:Portal/images/aliases]] - for adding aliases for existing portal names. Use this page for variations -- in spelling and diacritics, etc., no matter what letter the portal begins with. -- When adding entries, please use alphabetical order. The format of the images table entries is as follows: -- ["portal name"] = "image.svg", -- The portal name should be the name of your portal, in lower case. For example, the portal name for -- "Portal:United Kingdom" would be "united kingdom". The image name should be capitalised normally, and the "File:" -- namespace prefix should be omitted. ]==] return { ["oaxaca"] = "Flag of Oaxaca.svg|border|link=|alt=flag", ["occult"] = "Pentacle 2.svg|link=|alt=", ["oceania"] = "大洋.png|alt=icon", ["ocean"] = "Waves in pacifica 1.jpg|alt=icon", ["oceans"] = "Waves in pacifica 1.jpg|alt=icon", ["odense"] = "Coat of arms of Odense.svg|alt=icon", ["odessa"] = "Flag of Odessa.svg|alt=flag", ["odisha"] = "Seal of Odisha.png|link=|alt=seal", ["ohio"] = "Flag of Ohio.svg|link=|alt=flag", ["ohio wesleyan university"] = "ElliottHallOWU.jpg|link=|alt=photo", ["oklahoma"] = "Flag of Oklahoma.svg|border|link=|alt=flag", ["olives"] = "NCI 2 green olives.jpg|link=|alt=", ["olympic games"] = "Olympic Rings.svg|link=|alt=", ["olympics"] = "Olympic Rings.svg|link=|alt=", ["omaha"] = "Flag of Omaha, Nebraska.jpg|link=|alt=flag", ["oman"] = "Flag of Oman.svg|border|link=|alt=flag", ["ontario"] = "Flag of Ontario.svg|border|link=|alt=flag", ["ontario regions"] = "Ontario-flag-contour.png|link=|alt=", ["opera"] = "Operalogo.svg|alt=icon", ["oregon"] = "Flag of Oregon.svg|border|link=|alt=flag", ["organic chemistry"] = "Covalent.svg|alt=icon", ["organized labour"] = "Syndicalism.svg|alt=icon", ["oriental orthodoxy"] = "CopticCross.jpg|link=|alt=", ["origami"] = "Origami-crane.jpg|alt=icon", ["osaka"] = "Flag of Osaka City.svg|border|link=|alt=flag", ["osaka university"] = "Toyonaka stone.png|alt=icon", ["oscar wilde"] = "Oscar Wilde, 1882.jpg|link=|alt=", ["ossetian"] = "Idioma osetio.png|border|link=Ossetian language|alt=map", ["ottawa"] = "Flag of Ottawa, Ontario.svg|border|link=|alt=flag", ["ottoman empire"] = "Flag of the Ottoman Empire.svg|border|link=|alt=flag", ["outlines"] = "Global thinking.svg|link=|alt=", ["oxfordshire"] = "EnglandOxfordshire.png|alt=icon", ["oz"] = "Oz flag.svg|alt=icon" } fb254fb478a7be48fd87d03b9e5017a96ddb900c Template:Order of magnitude 10 137 290 289 2022-09-04T15:25:10Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{safesubst:<noinclude/>#ifexpr:{{{1|0}}}=0 |{{safesubst:<noinclude/>#ifexpr:abs{{{1|0}}}1=1 |0 |{{safesubst:<noinclude/>#expr:floor((ln(abs{{{1}}}1)/ln10)+1)}} }} |{{safesubst:<noinclude/>#expr:floor((ln(abs({{{1|0}}}) )/ln 10)+1E((abs{{{1|0}}}>1E100 or abs{{{1|0}}}<1E-100)-14))}} }}</includeonly><noinclude> {{documentation}} </noinclude> cede5694e8ebb404ecdd17ae1f8e1c5d19562728 Template:DEC 10 138 292 291 2022-09-04T15:25:10Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{Str rep|{{{1}}}|-|−}}&deg;{{#ifeq: {{{2|+}}}|{{{2|-}}}|&nbsp;{{{2|}}}&prime;|}}{{#ifeq: {{{3|+}}}|{{{3|-}}}|&nbsp;{{{3|}}}&Prime;|}}<noinclude> {{documentation}} </noinclude> 6927f28c38d0a50c1b2b56e84804d862ad50264a Template:RA 10 139 294 293 2022-09-04T15:25:11Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{nowrap|{{#if:{{{1|}}}|{{{1}}}<sup>h</sup>|}} {{#if:{{{2|}}}|{{{2}}}<sup>m</sup>|}} {{#if:{{{3|}}}|{{{3|}}}<sup>s</sup>|}}}}<noinclude> {{documentation}} </noinclude> f457f7f0663d084c3d3296af8b827dc417ce0ac4 Template:Sky 10 140 296 295 2022-09-04T15:25:11Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <noinclude></noinclude><includeonly>{{#ifeq:{{{display|}}}|inline|<span class="sky-coordinates-inline plainlinks nourlexpansion">[[File:Jupiter and moon.png|20px|link=|Sky map]] [http://www.wikisky.org/?ra={{#expr:{{trim|{{{1}}}}}+{{trim|{{{2}}}}}/60+{{trim|{{{3}}}}}/3600}}&de={{#expr:{{trim|{{{4|+}}}}}{{trim|{{{5}}}}}+{{trim|{{{4|+}}}}}{{trim|{{{6}}}}}/60+{{trim|{{{4|+}}}}}{{trim|{{{7}}}}}/3600}}&zoom={{#expr:ln{{{8|100000}}}/ln10+1 round 0}}&show_grid=1&show_constellation_lines=1&show_constellation_boundaries=1&show_const_names=1&show_galaxies=1&img_source=IMG_all {{trim|{{{1}}}}}<sup>h</sup> {{trim|{{{2}}}}}<sup>m</sup> {{trim|{{{3}}}}}<sup>s</sup>, {{#ifeq:{{trim|{{{4}}}}}|-|−|{{trim|{{{4}}}}} }}{{trim|{{{5}}}}}° {{trim|{{{6}}}}}′ {{trim|{{{7}}}}}″]</span>|<indicator name="01-sky-coordinates"><templatestyles src="Template:Sky/styles.css" /><!-- This mostly repeats the previous statement, but i'm to lazy to write a lua module for it, try to keep it in sync --><span class="sky-coordinates-display plainlinks nourlexpansion">[[Celestial coordinate system|Coordinates]]: [[File:Jupiter and moon.png|20px|link=|Sky map]] [http://www.wikisky.org/?ra={{#expr:{{trim|{{{1}}}}}+{{trim|{{{2}}}}}/60+{{trim|{{{3}}}}}/3600}}&de={{#expr:{{trim|{{{4|+}}}}}{{trim|{{{5}}}}}+{{trim|{{{4|+}}}}}{{trim|{{{6}}}}}/60+{{trim|{{{4|+}}}}}{{trim|{{{7}}}}}/3600}}&zoom={{#expr:ln{{{8|100000}}}/ln10+1 round 0}}&show_grid=1&show_constellation_lines=1&show_constellation_boundaries=1&show_const_names=1&show_galaxies=1&img_source=IMG_all {{trim|{{{1}}}}}<sup>h</sup> {{trim|{{{2}}}}}<sup>m</sup> {{trim|{{{3}}}}}<sup>s</sup>, {{#ifeq:{{trim|{{{4}}}}}|-|−|{{trim|{{{4}}}}} }}{{trim|{{{5}}}}}° {{trim|{{{6}}}}}′ {{trim|{{{7}}}}}″]</span></indicator> }}</includeonly><noinclude>{{documentation}}</noinclude> 0820a25c62d725441979785de033585a0ffa870e Template:Solar luminosity 10 141 298 297 2022-09-04T15:25:11Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#if:{{{1|}}} |{{{1}}}&nbsp; }}{{#if:{{{link|}}} |[[Solar luminosity|<var>L</var><sub>&#x2609;</sub>]] |<var>L</var><sub>&#x2609;</sub> }}<noinclude> {{documentation}} </noinclude> fb6372ee064d487f11d117a91d6ae84d9980f19f Template:Engvar 10 142 300 299 2022-09-04T15:25:11Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#invoke:Engvar|variants}}<noinclude> {{documentation}} </noinclude> 8a5e5d43fff0053bf6bd7fab7f761a6be4c05d21 Module:Engvar 828 143 302 301 2022-09-04T15:25:12Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain -- This module implements Template:Engvar. -- Template:Engvar is to be build into the template (like an infobox), with default & variant spellings defined. -- That template should also allow parameter '|engvar=' for the editor (article page). -- The module/template Engvar then returns the spelling variant as is set in that article (for example '|engvar=en-GB'). -- The defaultWord is returned, unless the engvar input hits on a defined (en-XX) variant word. local p = {} local getArgs = require('Module:Arguments').getArgs local gsub = string.gsub local lower = string.lower local upper = string.upper function p.variants(frame) local args = getArgs(frame) return p._variants(args) end function p._variants(args) local returnWord = nil local defaultWord = args.defaultWord or '' if args.engvar == nil then -- Nothing to look for; use defaultWord right away returnWord = defaultWord elseif args.defaultLang == gsub(lower(args.engvar), '^en%-(%w%w)$', formatISO) then -- By the defaultLang, the defaultWord is asked returnWord = defaultWord else returnWord = args[gsub(lower(args.engvar), '^en%-(%w%w)$', formatISO)] end if returnWord == nil then -- No hit so far. Search by words in the engvar entered, checking the list local useLang = engvarLang(args.engvar) if useLang == nil then returnWord = defaultWord .. addMaintCat(args) else returnWord = args[useLang] or defaultWord end end return returnWord end -- Returns arguments and intermediate result. Plus the template result, in front. function p.explain(frame) local args = getArgs(frame) local ret = {} table.insert(ret, '\n\n: Settings:') table.insert(ret, 'defaultWord=' .. (args.defaultWord or '') .. '; ') table.insert(ret, 'defaultLang=' .. (args.defaultLang or '') .. '; ') table.insert(ret, 'engvarCat=' .. (args.engvarCat or '[default:yes]') .. '; ') table.insert(ret, 'engvarCatSort=' .. (args.engvarCatSort or '')) table.insert(ret, '\n\n: engvar=' .. (args.engvar or '') .. ' [input] ') local useLang = engvarLang(args.engvar or '') table.insert(ret, ' => Engvar code [used]: >' .. (useLang or '') .. '<.') for k, v in pairs(args) do if k == 'en-UK' then table.insert(ret, k .. ' ? better: use "en-GB"; ') elseif k == 'en-SA' then table.insert(ret, k .. ' ? misleading; use "en-ZA"; ') end if k == 'defaultWord' then elseif k == 'defaultLang' then elseif k == 'engvar' then elseif k == 'engvarcat' then elseif k == gsub(lower(k), '^en%-(%w%w)$', formatISO) then table.insert(ret, k .. '=' .. v .. '; ') else table.insert(ret, k .. ' [not standard:]=' .. v .. '; ') end end return (args.engvar or '') .. ' => ' .. p._variants(args) .. table.concat(ret, ' ') end -- Turn a match into pattern 'en-XX' function formatISO(country) return ('en-' .. upper(country) or '') end function engvarLang(searchEngvar) -- Search verbose language identifiers to ISO-format 'en-XX' -- Assumed: not a blank string '' to search local match = string.match searchEngvar = gsub(searchEngvar, '^%s*en%-(.*)', '%1') -- rm any opening 'en-'. searchEngvar = gsub(lower(searchEngvar), '[%s%(%)%-]', '') -- To lc, remove all: (, ) , ws, hyphen. local useLang --Special codes if match(searchEngvar, 'oxford') or searchEngvar == 'oed' then useLang = 'en-OED' -- 'oxford' to catch before anyting 'british' elseif match(searchEngvar, 'iupac') then useLang = 'en-IUPAC' -- chemistry -- Very often used elseif match(searchEngvar, 'british') or searchEngvar == 'uk' or searchEngvar == 'gbr' then useLang = 'en-GB' elseif searchEngvar == 'us' or match(searchEngvar, 'unitedstates') or searchEngvar == 'american' or searchEngvar == 'usa' then useLang = 'en-US' elseif match(searchEngvar, 'australia') or searchEngvar == 'aus' then useLang = 'en-AU' -- Often used elseif match(searchEngvar, 'india') or searchEngvar == 'ind' then useLang = 'en-IN' elseif searchEngvar == 'newzealand' or searchEngvar == 'nzl' then useLang = 'en-NZ' elseif match(searchEngvar, 'southafrica') -- not: en-SA or searchEngvar == 'zaf' then useLang = 'en-ZA' elseif searchEngvar == 'canada' or searchEngvar == 'can' then useLang = 'en-CA' elseif match(searchEngvar, 'hiberno') or match(searchEngvar, 'ireland') or match(searchEngvar, 'irish') or searchEngvar == 'irl' then useLang = 'en-EI' elseif match(searchEngvar, 'hongkong') or searchEngvar == 'hkg' then useLang = 'en-HK' -- Less often used elseif match(searchEngvar, 'jamaica') or searchEngvar == 'jam' then useLang = 'en-JM' elseif match(searchEngvar, 'malawi') or searchEngvar == 'mwi' then useLang = 'en-MW' elseif match(searchEngvar, 'nigeria') or searchEngvar == 'nga' then useLang = 'en-NG' elseif match(searchEngvar, 'pakistan') or searchEngvar == 'pak' then useLang = 'en-PK' elseif match(searchEngvar, 'philippine') or searchEngvar == 'phl' then useLang = 'en-PH' elseif match(searchEngvar, 'scotland') or match(searchEngvar, 'scottish') or searchEngvar == 'sco' then useLang = 'en-SCO' -- Has no alpha-2 code; not 'scotch' elseif match(searchEngvar, 'singapore') or searchEngvar == 'sgp' then useLang = 'en-SG' elseif match(searchEngvar, 'trinidad') or match(searchEngvar, 'tobago') or searchEngvar == 'tto' then useLang = 'en-TT' else useLang = nil end return useLang end function addMaintCat(args) local catMaintenance if args.engvarCat == 'no' then else local title = mw.title.getCurrentTitle() if title:inNamespaces(0) then -- 0=main, 10=templ, 828=module if args.engvarCatSort then catMaintenance = '|' .. args.engvarCatSort .. ', ' .. title.text end catMaintenance = '[[Category:Articles using an unknown Template:Engvar option' .. (catMaintenance or '') .. ']]' end end return catMaintenance or '' end return p c67c97cf2bc643d26781b77fd4b0d63383ab47a8 Template:End 10 144 304 303 2022-09-04T15:25:13Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly> {{#if:{{{html|}}}|</table>|{{!}}} }}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using end template with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:End]] with unknown parameter "_VALUE_"|ignoreblank=y| html | 1<!--parameter does not do anything, but described in the documentation since 2015--> }}<noinclude>{{Documentation}}</noinclude> 6da317c960412bc7ac63866ddd9237d1a9bd914e Template:Rnd 10 145 306 305 2022-09-04T15:25:13Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki #REDIRECT [[Template:Round]] 60d43fe6637b72ea57395979124e0c4cea5b4f9e Template:Solar mass 10 146 308 307 2022-09-04T15:25:14Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#if:{{{1|}}} |{{{1}}}&nbsp; }}{{#if:{{{link|}}} |[[Solar mass|<var>M</var><sub>&#x2609;</sub>]] |<var>M</var><sub>&#x2609;</sub> }}<noinclude> {{documentation}} </noinclude> 2a303d9d8a727c9f9ccc23508e1d17883808fbcc Template:Solar radius 10 147 310 309 2022-09-04T15:25:14Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{#if:{{{1|}}} |{{{1}}}&nbsp; }}{{#if:{{{link|}}} |[[Solar radius|<var>R</var><sub>&#x2609;</sub>]] |<var>R</var><sub>&#x2609;</sub> }}<noinclude> {{documentation}} </noinclude> 12c29f2ba83c64dcc96a015a59244428c531f452 Template:Lang-zh 10 148 312 311 2022-09-04T15:25:14Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#invoke:Lang-zh|Zh}}</includeonly><noinclude>{{documentation}}</noinclude> 09d0f2945fa94b8947d29d2329101bd511d11d2d Template:Zh 10 149 314 313 2022-09-04T15:25:15Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki #REDIRECT [[Template:Lang-zh]] {{R from move}} 6aa0af2f0918a28a55a7aa2f294fc53068c3b191 Module:Lang-zh 828 150 316 315 2022-09-04T15:25:15Z SpaceMan 2 1 revision imported: Canopus Scribunto text/plain require('Module:No globals') local p = {} -- articles in which traditional Chinese preceeds simplified Chinese local t1st = { ["228 Incident"] = true, ["Chinese calendar"] = true, ["Lippo Centre, Hong Kong"] = true, ["Republic of China"] = true, ["Republic of China at the 1924 Summer Olympics"] = true, ["Taiwan"] = true, ["Taiwan (island)"] = true, ["Taiwan Province"] = true, ["Wei Boyang"] = true, } -- the labels for each part local labels = { ["c"] = "Chinese", ["s"] = "simplified Chinese", ["t"] = "traditional Chinese", ["p"] = "pinyin", ["tp"] = "Tongyong Pinyin", ["w"] = "Wade–Giles", ["j"] = "Jyutping", ["cy"] = "Cantonese Yale", ["sl"] = "Sidney Lau", ["poj"] = "Pe̍h-ōe-jī", ["zhu"] = "Zhuyin Fuhao", ["l"] = "lit.", ["tr"] = "trans.", } -- article titles for wikilinks for each part local wlinks = { ["c"] = "Chinese language", ["s"] = "simplified Chinese characters", ["t"] = "traditional Chinese characters", ["p"] = "pinyin", ["tp"] = "Tongyong Pinyin", ["w"] = "Wade–Giles", ["j"] = "Jyutping", ["cy"] = "Yale romanization of Cantonese", ["sl"] = "Sidney Lau romanisation", ["poj"] = "Pe̍h-ōe-jī", ["zhu"] = "Bopomofo", ["l"] = "Literal translation", ["tr"] = "Translation", } -- for those parts which are to be treated as languages their ISO code local ISOlang = { ["c"] = "zh", ["t"] = "zh-Hant", ["s"] = "zh-Hans", ["p"] = "zh-Latn-pinyin", ["tp"] = "zh-Latn", ["w"] = "zh-Latn-wadegile", ["j"] = "yue-Latn-jyutping", ["cy"] = "yue-Latn", ["sl"] = "yue-Latn", ["poj"] = "nan-Latn", ["zhu"] = "zh-Bopo", } local italic = { ["p"] = true, ["tp"] = true, ["w"] = true, ["j"] = true, ["cy"] = true, ["sl"] = true, ["poj"] = true, } local superscript = { ["w"] = true, ["sl"] = true, } -- Categories for different kinds of Chinese text local cats = { ["c"] = "[[Category:Articles containing Chinese-language text]]", ["s"] = "[[Category:Articles containing simplified Chinese-language text]]", ["t"] = "[[Category:Articles containing traditional Chinese-language text]]", } function p.Zh(frame) -- load arguments module to simplify handling of args local getArgs = require('Module:Arguments').getArgs local args = getArgs(frame) return p._Zh(args) end function p._Zh(args) local uselinks = not (args["links"] == "no") -- whether to add links local uselabels = not (args["labels"] == "no") -- whether to have labels local capfirst = args["scase"] ~= nil local t1 = false -- whether traditional Chinese characters go first local j1 = false -- whether Cantonese Romanisations go first local testChar if (args["first"]) then for testChar in mw.ustring.gmatch(args["first"], "%a+") do if (testChar == "t") then t1 = true end if (testChar == "j") then j1 = true end end end if (t1 == false) then local title = mw.title.getCurrentTitle() t1 = t1st[title.text] == true end -- based on setting/preference specify order local orderlist = {"c", "s", "t", "p", "tp", "w", "j", "cy", "sl", "poj", "zhu", "l", "tr"} if (t1) then orderlist[2] = "t" orderlist[3] = "s" end if (j1) then orderlist[4] = "j" orderlist[5] = "cy" orderlist[6] = "sl" orderlist[7] = "p" orderlist[8] = "tp" orderlist[9] = "w" end -- rename rules. Rules to change parameters and labels based on other parameters if args["hp"] then -- hp an alias for p ([hanyu] pinyin) args["p"] = args["hp"] end if args["tp"] then -- if also Tongyu pinyin use full name for Hanyu pinyin labels["p"] = "Hanyu Pinyin" end if (args["s"] and args["s"] == args["t"]) then -- Treat simplified + traditional as Chinese if they're the same args["c"] = args["s"] args["s"] = nil args["t"] = nil elseif (not (args["s"] and args["t"])) then -- use short label if only one of simplified and traditional labels["s"] = labels["c"] labels["t"] = labels["c"] end local body = "" -- the output string local params -- for creating HTML spans local label -- the label, i.e. the bit preceeding the supplied text local val -- the supplied text -- go through all possible fields in loop, adding them to the output for i, part in ipairs(orderlist) do if (args[part]) then -- build label label = "" if (uselabels) then label = labels[part] if (capfirst) then label = mw.language.getContentLanguage():ucfirst(label) capfirst = false end if (uselinks) then label = "[[" .. wlinks[part] .. "|" .. label .. "]]" end if (labels[part] ~= "lit.") then label = label .. "&#58;" else label = "<small>" .. label .. "</small>" end label = label .. " " end -- build value val = args[part] if (cats[part]) and mw.title.getCurrentTitle().namespace == 0 then -- if has associated category AND current page in article namespace, add category val = cats[part] .. val end if (ISOlang[part]) then -- add span for language if needed params = {["lang"] = ISOlang[part]} val = mw.text.tag({name="span",attrs=params, content=val}) elseif ((part == "l") or (part == "tr")) then -- put literals in quotes val = "'" .. val .. "'" end if (italic[part]) then -- italicise val = "<i>" .. val .. "</i>" end if string.match(val, "</?sup>") then val = val.."[[Category:Pages using template Zh with sup tags]]" end if (superscript[part]) then -- superscript val = val:gsub("(%d)", "<sup>%1</sup>"):gsub("(%d)</sup>%*<sup>(%d)", "%1*%2"):gsub("<sup><sup>([%d%*]+)</sup></sup>", "<sup>%1</sup>") end -- add both to body body = body .. label .. val .. "; " end end if (body > "") then -- check for empty string return string.sub(body, 1, -3) -- chop off final semicolon and space else --no named parameters; see if there's a first parameter, ignoring its name if (args[1]) then -- if there is treat it as Chinese label = "" if (uselabels) then label = labels["c"] if (uselinks) then label = "[[" .. wlinks["c"] .. "|" .. label .. "]]" end label = label .. "&#58; " end -- default to show links and labels as no options given if mw.title.getCurrentTitle().namespace == 0 then -- if current page in article namespace val = cats["c"] .. args[1] else val = args[1] end params = {["lang"] = ISOlang["c"]} val = mw.text.tag({name="span",attrs=params, content=val}) return label .. val end return "" end end return p 784d83ce2141b8e5828575b09c81e5f62a637998 Template:ErrorBar2 10 151 318 317 2022-09-04T15:25:15Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <includeonly>{{#if:{{{2|}}}|{{#ifexpr: abs({{{2}}}) > abs({{{1}}} * {{{3}}})|approx. {{rnd|{{{1}}}|-{{order of magnitude|{{{2}}}}}}}|{{rnd|{{{1}}}|-{{order of magnitude|{{{2}}}}} }} ± {{rnd|{{{2}}}|-{{order of magnitude|{{{2}}}}} }} }} |{{{1}}} }}</includeonly><noinclude> {{documentation}} </noinclude> 7d3a83f90aace7dc6b51a308b64364e74e8bc666 Template:Starbox astrometry 10 152 320 319 2022-09-04T15:25:16Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><th style="background-color: #FFFFC0; text-align: center;" colspan="2">{{#if:{{{no_heading|}}}||[[Astrometry]]}}</th></tr>{{#if:{{{component|}}}|<tr style="text-align:center"><th colspan="2">{{{component}}}</th></tr>}}</th></tr><!-- --><tr><th colspan="2" style="text-align: center">{{{component1<includeonly>|</includeonly>}}}</tr><!-- -->{{#if:{{{radial_v<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Radial velocity]] (R<sub>v</sub>)'''</td><td>{{{radial_v}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{total_v<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''Total velocity'''</td><td>{{{total_v}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{prop_mo_ra<includeonly>|</includeonly>}}}{{{prop_mo_dec|}}}|<tr style="vertical-align:top;"><td>'''[[Proper motion]] (μ)'''</td><td> <abbr title="Right Ascension">RA:</abbr>&nbsp;{{{prop_mo_ra|}}}&nbsp;[[Milliarcsecond|mas]]/[[Year|yr]]{{{pm_footnote|}}} <br /> <abbr title="Declination">Dec.:</abbr>&nbsp;{{{prop_mo_dec|}}}&nbsp;[[Milliarcsecond|mas]]/[[Year|yr]]{{{pm_footnote|}}} </td></tr> }}<!-- -->{{#if:{{{parallax<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Stellar parallax|Parallax]] (π)'''</td><td>{{{parallax}}}{{#if:{{{p_error|}}}|&nbsp;±&nbsp;{{{p_error}}} }}&nbsp;[[Milliarcsecond|mas]]{{#if:{{{parallax_footnote|}}}|{{{parallax_footnote}}} }}</td></tr>}}<!-- -->{{#if:{{{dist_ly<includeonly>|</includeonly>}}}{{{dist_pc|}}}{{#if:{{{parallax|}}}|{{#if:{{{p_error|}}}|{{#ifexpr: {{{parallax|}}}-{{{p_error|}}}>0|yes}}}}}}|<tr style="vertical-align:top;"><td>'''[[Distance (astronomy)|Distance]]'''</td><!-- --><td><!-- -->{{#if:{{{dist_ly<includeonly>|</includeonly>}}}{{{dist_pc|}}}||{{ErrorBar2|{{#expr: 3261.5638 / {{{parallax}}} }}|{{#if:{{{p_error|}}}|{{#expr: 3261.5638 * {{{p_error}}} / ({{{parallax}}} * {{{parallax}}}) }} }}|0.1}}&nbsp;[[Light-year|ly]] <br />({{ErrorBar2|{{#expr: 1000.0 / {{{parallax}}} }}|{{#if:{{{p_error|}}}|{{#expr: 1000.0 * {{{p_error}}} / ({{{parallax}}} * {{{parallax}}}) }} }}|0.1}}&nbsp;[[Parsec|pc]])}}<!-- -->{{#if:{{{dist_ly<includeonly>|</includeonly>}}}|{{{dist_ly}}}&nbsp;[[Light-year|ly]] {{#if:{{{dist_pc|}}}|<br />({{{dist_pc}}}&nbsp;[[Parsec|pc]])}}|{{#if:{{{dist_pc|}}}|{{{dist_pc}}}&nbsp;[[Parsec|pc]]}}}}{{{dist_footnote|}}}<!-- --></td></tr>}}<!-- -->{{#if:{{{absmag_v<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Absolute magnitude|Absolute&nbsp;magnitude]]&nbsp;(M<sub>V</sub>)'''</td><td>{{{absmag_v}}}</td></tr>}}<!-- -->{{#if:{{{absmag_bol<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Absolute magnitude|Absolute&nbsp;bolometric<br>magnitude]]&nbsp;(M<sub>bol</sub>)'''</td><td>{{{absmag_bol}}}</td></tr>}}<!-- --><tr><th colspan="2" style="text-align: center">{{{component2<includeonly>|</includeonly>}}}</th></tr><!-- -->{{#if:{{{radial_v2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Radial velocity]] (R<sub>v</sub>)'''</td><td>{{{radial_v2}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{total_v2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''Total velocity'''</td><td>{{{total_v2}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{prop_mo_ra2<includeonly>|</includeonly>}}}{{{prop_mo_dec2|}}}|<tr style="vertical-align:top;"><td>'''[[Proper motion]] (μ)'''</td><td> <abbr title="Right Ascension">RA:</abbr>&nbsp;{{{prop_mo_ra2|-}}}&nbsp;[[Milliarcsecond|mas]]/[[Year|yr]]{{{pm_footnote2|}}} <br /> <abbr title="Declination">Dec.:</abbr>&nbsp;{{{prop_mo_dec2|-}}}&nbsp;[[Milliarcsecond|mas]]/[[Year|yr]]{{{pm_footnote2|}}} </td></tr> }}<!-- -->{{#if:{{{parallax2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Stellar parallax|Parallax]] (π)'''</td><td>{{{parallax2}}}{{#if:{{{p_error2|}}}|&nbsp;±&nbsp;{{{p_error2}}}}}&nbsp;[[Milliarcsecond|mas]]{{#if:{{{parallax_footnote2|}}}|{{{parallax_footnote2}}}}}</td></tr>}}<!-- -->{{#if:{{{dist_ly2<includeonly>|</includeonly>}}}{{{dist_pc2|}}}{{{parallax2|}}}|<tr style="vertical-align:top;"><td>'''[[Distance (astronomy)|Distance]]'''</td><!-- --><td><!-- -->{{#if:{{{dist_ly2<includeonly>|</includeonly>}}}{{{dist_pc2|}}}||{{ErrorBar2|{{#expr: 3261.5638 / {{{parallax2}}} }}|{{#if:{{{p_error2|}}}|{{#expr: 3261.5638 * {{{p_error2}}} / ({{{parallax2}}} * {{{parallax2}}}) }} }}|0.1}}&nbsp;[[Light-year|ly]] <br />({{ErrorBar2|{{#expr: 1000.0 / {{{parallax2}}} }}|{{#if:{{{p_error2|}}}|{{#expr: 1000.0 * {{{p_error2}}} / ({{{parallax2}}} * {{{parallax2}}}) }} }}|0.1}}&nbsp;[[Parsec|pc]])}}<!-- -->{{#if:{{{dist_ly<includeonly>|</includeonly>}}}|{{{dist_ly2}}}&nbsp;[[Light-year|ly]] {{#if:{{{dist_pc2|}}}|<br />({{{dist_pc2}}}&nbsp;[[Parsec|pc]])}}|{{#if:{{{dist_pc2|}}}|{{{dist_pc2}}}&nbsp;[[Parsec|pc]]}}}}<!-- --></td></tr>}}<!-- -->{{#if:{{{absmag_v2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Absolute magnitude|Absolute&nbsp;magnitude]]&nbsp;(M<sub>V</sub>)'''</td><td>{{{absmag_v2}}}</td></tr>}}<!-- -->{{#if:{{{absmag_bol2<includeonly>|</includeonly>}}}|<tr style="vertical-align:top;"><td>'''[[Absolute magnitude|Absolute&nbsp;bolometric<br>magnitude]]&nbsp;(M<sub>bol</sub>)'''</td><td>{{{absmag_bol2}}}</td></tr>}}<noinclude> |} {{Documentation}} </noinclude> e92454f250713fd8ce29da215c7da5e8ac87b802 Template:Starbox begin 10 153 322 321 2022-09-04T15:25:16Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {| class="infobox" style="width: 22em; font-size: 88%; <!-- text-align: left; --> line-height: 1.5em" |+ style="font-size: 125%; font-weight: bold" | {{{name<includeonly>|{{PAGENAME}}</includeonly>}}}<noinclude> |}{{Documentation}}</noinclude> 115f5bb26dd6bc3e6032bfe5080e62fffdb69a80 Template:Starbox catalog 10 154 324 323 2022-09-04T15:25:17Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><th style="background-color: #FFFFC0; text-align: center;" colspan="2">[[Star catalogue|Other designations]]</th></tr><!-- --><tr><td colspan="2"><div style="width: 250px;"> {{{names<includeonly>|</includeonly>}}} </div></td></tr><!-- -->{{#if:{{{component1<includeonly>|</includeonly>}}}|<tr><td colspan="2">'''{{{component1}}}''': {{{names1}}}</td></tr>}}<!-- -->{{#if:{{{component2<includeonly>|</includeonly>}}}|<tr><td colspan="2">'''{{{component2}}}''': {{{names2}}}</td></tr>}}<!-- -->{{#if:{{{component3<includeonly>|</includeonly>}}}|<tr><td colspan="2">'''{{{component3}}}''': {{{names3}}}</td></tr>}}<!-- -->{{#if:{{{component4<includeonly>|</includeonly>}}}|<tr><td colspan="2">'''{{{component4}}}''': {{{names4}}}</td></tr>}}<noinclude> |} {{Documentation}} </noinclude> 5a833fd635cee397f343a44ca1cb8ea26ae44be3 Template:Starbox character 10 155 326 325 2022-09-04T15:25:17Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude> |- ! style="background-color: #FFFFC0; text-align: center;" colspan="2"| {{#if:{{{no_heading|}}}||Characteristics}} |- {{#if:{{{component|}}}| ! style="text-align:center" colspan="2" {{!}} {{{component}}} }} |- {{#if:{{{component1|}}}| ! style="text-align:center" colspan="2" {{!}} {{{component1}}} }} |- style="vertical-align:top" {{#if:{{{type|}}}| ! style="text-align:left" {{!}} [[Stellar evolution|Evolutionary&nbsp;stage]] {{!}} {{{type}}} }} |- style="vertical-align:top" {{#if:{{{class|}}}| ! style="text-align:left" {{!}} [[Stellar classification|Spectral&nbsp;type]] {{!}} {{{class}}} }} |- style="vertical-align:top" {{#if:{{{appmag_1_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude]]&nbsp;({{{appmag_1_passband|}}}) {{!}} {{{appmag_1}}} }} |- style="vertical-align:top" {{#if:{{{appmag_2_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_2_passband|}}}) {{!}} {{{appmag_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_3_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_3_passband|}}}) {{!}} {{{appmag_3}}} }} |- style="vertical-align:top" {{#if:{{{appmag_4_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_4_passband|}}}) {{!}} {{{appmag_4}}} }} |- style="vertical-align:top" {{#if:{{{appmag_5_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_5_passband|}}}) {{!}} {{{appmag_5}}} }} |- style="vertical-align:top" {{#if:{{{appmag_6_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_6_passband|}}}) {{!}} {{{appmag_6}}} }} |- style="vertical-align:top" {{#if:{{{appmag_7_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_7_passband|}}}) {{!}} {{{appmag_7}}} }} |- style="vertical-align:top" {{#if:{{{appmag_8_passband|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_8_passband|}}}) {{!}} {{{appmag_8}}} }} |- style="vertical-align:top" {{#if:{{{u-b|}}}| ! style="text-align:left" {{!}} U−B {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{u-b}}} }} |- style="vertical-align:top" {{#if:{{{b-v|}}}| ! style="text-align:left" {{!}} B−V {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{b-v}}} }} |- style="vertical-align:top" {{#if:{{{v-r|}}}| ! style="text-align:left" {{!}} V−R {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{v-r}}} }} |- style="vertical-align:top" {{#if:{{{r-i|}}}| ! style="text-align:left" {{!}} R−I {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{r-i}}} }} |- style="vertical-align:top" {{#if:{{{j-h|}}}| ! style="text-align:left" {{!}} J−H {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{j-h}}} }} |- style="vertical-align:top" {{#if:{{{j-k|}}}| ! style="text-align:left" {{!}} J−K {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{j-k}}} }} |- style="vertical-align:top" {{#if:{{{variable|}}}| ! style="text-align:left" {{!}} [[Variable star|Variable&nbsp;type]] {{!}} {{{variable}}} }} |- style="vertical-align:top" {{#if:{{{component2|}}}| ! style="text-align:center" colspan="2" {{!}} {{{component2}}} }} |- style="vertical-align:top" {{#if:{{{type2|}}}| ! style="text-align:left" {{!}} [[Stellar evolution|Evolutionary&nbsp;stage]] {{!}} {{{type2}}} }} |- style="vertical-align:top" {{#if:{{{class2|}}}| ! style="text-align:left" {{!}} [[Stellar classification|Spectral&nbsp;type]] {{!}} {{{class2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_1_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude]]&nbsp;({{{appmag_1_passband2|}}}) {{!}} {{{appmag_1_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_2_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_2_passband2|}}}) {{!}} {{{appmag_2_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_3_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_3_passband2|}}}) {{!}} {{{appmag_3_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_4_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_4_passband2|}}}) {{!}} {{{appmag_4_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_5_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_5_passband2|}}}) {{!}} {{{appmag_5_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_6_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_6_passband2|}}}) {{!}} {{{appmag_6_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_7_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_7_passband2|}}}) {{!}} {{{appmag_7_2}}} }} |- style="vertical-align:top" {{#if:{{{appmag_8_passband2|}}}| ! style="text-align:left" {{!}} [[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;({{{appmag_8_passband2|}}}) {{!}} {{{appmag_8_2}}} }} |- style="vertical-align:top" {{#if:{{{u-b2|}}}| ! style="text-align:left" {{!}} U−B {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{u-b2}}} }} |- style="vertical-align:top" {{#if:{{{b-v2|}}}| ! style="text-align:left" {{!}} B−V {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{b-v2}}} }} |- style="vertical-align:top" {{#if:{{{v-r2|}}}| ! style="text-align:left" {{!}} V−R {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{v-r2}}} }} |- style="vertical-align:top" {{#if:{{{r-i2|}}}| ! style="text-align:left" {{!}} R−I {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{r-i2}}} }} |- style="vertical-align:top" {{#if:{{{j-h2|}}}| ! style="text-align:left" {{!}} J−H {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{j-h2}}} }} |- style="vertical-align:top" {{#if:{{{j-k2|}}}| ! style="text-align:left" {{!}} J−K {{engvar |defaultWord=[[color index]] |defaultLang=en-US |en-UK=[[colour index]] |engvar={{{engvar|}}} }} {{!}} {{{j-k2}}} }} |- style="vertical-align:top" {{#if:{{{variable2|}}}| ! style="text-align:left" {{!}} [[Variable star|Variable&nbsp;type]] {{!}} {{{variable2}}} }}<noinclude> |} {{Documentation}} </noinclude> bd7d2ca5352dd7b2dc3f58a1ac88cd9daf7194e3 Template:Starbox detail 10 156 328 327 2022-09-04T15:25:18Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><th style="background-color: #FFFFC0; text-align: center;" colspan="2">{{#if:{{{no_heading|}}}||Details{{{source|}}}}}</th></tr>{{#if:{{{component|}}}|<tr style="text-align:center"><th colspan="2">{{{component}}}</th></tr>}}</th></tr><!-- --><tr><th colspan="2" style="text-align: center">{{{component1<includeonly>|</includeonly>}}}</th></tr><!-- -->{{#if:{{{mass<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar mass|Mass]]'''</td><td>{{{mass}}}&nbsp;{{Solar mass|link=yes}}</td></tr>}}<!-- -->{{#if:{{{mass_mj<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar mass|Mass]]'''</td><td>{{{mass_mj}}}&nbsp;[[Jupiter mass|''M''<sub>Jup</sub>]]</td></tr>}}<!-- -->{{#if:{{{radius<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius}}}&nbsp;{{Solar radius|link=yes}}</td></tr>}}<!-- -->{{#if:{{{radius_rj<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius_rj}}}&nbsp;[[Jupiter radius|''R''<sub>Jup</sub>]]</td></tr>}}<!-- -->{{#if:{{{radius_km<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius_km}}}&nbsp;[[kilometer|km]]</td></tr>}}<!-- -->{{#if:{{{luminosity<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Luminosity]]'''</td><td>{{{luminosity}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{luminosity_bolometric<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity (bolometric)'''</td><td>{{{luminosity_bolometric}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{luminosity_visual<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity (visual, L<sub>V</sub>)'''</td><td>{{{luminosity_visual}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{habitable_inner<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline:"><td>'''[[Habitable zone]] inner limit'''</td><td>{{{habitable_inner}}}</td></tr>}}<!-- -->{{#if:{{{habitable_outer<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline:"><td>'''[[Habitable zone]] outer limit'''</td><td>{{{habitable_outer}}}</td></tr>}}<!-- -->{{#if:{{{gravity<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Surface gravity]] (log&nbsp;''g'')'''</td><td>{{{gravity}}}&nbsp;[[Centimetre–gram–second system of units|cgs]]</td></tr>}}<!-- -->{{#if:{{{temperature<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Effective temperature|Temperature]]'''</td><td>{{{temperature}}}&nbsp;[[Kelvin|K]]</td></tr>}}<!-- -->{{#if:{{{metal<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Metallicity]]'''</td><td>{{{metal}}}</td></tr>}}<!-- -->{{#if:{{{metal_fe<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Metallicity]]''' [Fe/H]</td><td>{{{metal_fe}}}&nbsp;[[Decimal exponent|dex]]</td></tr>}}<!-- -->{{#if:{{{rotation<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar rotation|Rotation]]'''</td><td>{{{rotation}}}</td></tr>}}<!-- -->{{#if:{{{rotational_velocity<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Projected rotational velocity|Rotational velocity]] (''v''&nbsp;sin&nbsp;''i'')'''</td><td>{{{rotational_velocity}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{age<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar evolution|Age]]'''</td><td>{{{age}}}&nbsp;years</td></tr>}}<!-- -->{{#if:{{{age_myr<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>{{#if:{{{age|}}}|&nbsp;|'''[[Stellar evolution|Age]]'''}}</td><td>{{{age_myr}}}&nbsp;[[megayear|Myr]]</td></tr>}}<!-- -->{{#if:{{{age_gyr<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>{{#if:{{{age|}}}|&nbsp;|'''[[Stellar evolution|Age]]'''}}</td><td>{{{age_gyr}}}&nbsp;[[gigayear|Gyr]]</td></tr>}}<!-- --><tr><th colspan="2" style="text-align: center">{{{component2<includeonly>|</includeonly>}}}</th></tr><!-- -->{{#if:{{{mass2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar mass|Mass]]'''</td><td>{{{mass2}}}&nbsp;{{Solar mass|link=yes}}</td></tr>}}<!-- -->{{#if:{{{mass_mj2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar mass|Mass]]'''</td><td>{{{mass_mj2}}}&nbsp;[[Jupiter mass|''M''<sub>Jup</sub>]]</td></tr>}}<!-- -->{{#if:{{{radius2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius2}}}&nbsp;{{Solar radius|link=yes}}</td></tr>}}<!-- -->{{#if:{{{radius_rj2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius_rj2}}}&nbsp;[[Jupiter radius|''R''<sub>Jup</sub>]]</td></tr>}}<!-- -->{{#if:{{{radius_km2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Radius]]'''</td><td>{{{radius_km2}}}&nbsp;[[kilometer|km]]</td></tr>}}<!-- -->{{#if:{{{luminosity2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity'''</td><td>{{{luminosity2}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{luminosity_bolometric2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity (bolometric)'''</td><td>{{{luminosity_bolometric2}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{luminosity_visual2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''Luminosity (visual, L<sub>V</sub>)'''</td><td>{{{luminosity_visual2}}}&nbsp;{{Solar luminosity|link=yes}}</td></tr>}}<!-- -->{{#if:{{{habitable_inner2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline:"><td>'''[[Habitable zone]] inner limit'''</td><td>{{{habitable_inner2}}}</td></tr>}}<!-- -->{{#if:{{{habitable_outer2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline:"><td>'''[[Habitable zone]] outer limit'''</td><td>{{{habitable_outer2}}}</td></tr>}}<!-- -->{{#if:{{{gravity2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Surface gravity]] (log&nbsp;''g'')'''</td><td>{{{gravity2}}}&nbsp;[[Centimetre–gram–second system of units|cgs]]</td></tr>}}<!-- -->{{#if:{{{temperature2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Effective temperature|Temperature]]'''</td><td>{{{temperature2}}}&nbsp;[[Kelvin|K]]</td></tr>}}<!-- -->{{#if:{{{metal2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Metallicity]]'''</td><td>{{{metal2}}}</td></tr>}}<!-- -->{{#if:{{if empty|{{{metal_fe2|}}}|{{{metal2_fe|}}}|<noinclude>x</noinclude>}}|<tr style="vertical-align:baseline;"><td>'''[[Metallicity]]''' [Fe/H]</td><td>{{{metal2_fe|{{{metal_fe2}}}}}}&nbsp;[[Decimal exponent|dex]]</td></tr>}}<!-- -->{{#if:{{{rotation2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Stellar rotation|Rotation]]'''</td><td>{{{rotation2}}}</td></tr>}}<!-- -->{{#if:{{{rotational_velocity2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Projected rotational velocity|Rotational velocity]] (''v''&nbsp;sin&nbsp;''i'')'''</td><td>{{{rotational_velocity2}}}&nbsp;km/s</td></tr>}}<!-- -->{{#if:{{{age2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>'''[[Star#Age_and_size_of_stars|Age]]'''</td><td>{{{age2}}}&nbsp;years</td></tr>}}<!-- -->{{#if:{{{age_myr2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>{{#if:{{{age2|}}}|&nbsp;|'''[[Star#Age_and_size_of_stars|Age]]'''}}</td><td>{{{age_myr2}}}&nbsp;[[megayear|Myr]]</td></tr>}}<!-- -->{{#if:{{{age_gyr2<includeonly>|</includeonly>}}}|<tr style="vertical-align:baseline;"><td>{{#if:{{{age2|}}}|&nbsp;|'''[[Star#Age_and_size_of_stars|Age]]'''}}</td><td>{{{age_gyr2}}}&nbsp;[[gigayear|Gyr]]</td></tr>}}<noinclude> |} <!-- Please add categories to the /doc subpage; interwikis go to Wikidata, thank you! --> {{Documentation}} </noinclude> 7f2d91f20c11e77a3a015d033ec4771978d97588 Template:Starbox end 10 157 330 329 2022-09-04T15:25:18Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki #REDIRECT [[Template:End]] {{Rcat shell| {{Wikidata redirect}} {{R from template shortcut}} {{R with history}} }} ad342c0433bda993d648e9da241703291bbb98a6 Template:Starbox image 10 158 332 331 2022-09-04T15:25:19Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><td colspan="2" style="text-align:center;"><div style="text-align: center; margin-left:auto; margin-right:auto">{{{image}}}{{#ifeq:{{#invoke:String|sub|{{{image}}}|1|4}}|<div||<br/>}}{{{caption}}}{{#if:{{{credit|}}}|<br>'''Credit''': ''{{{credit}}}''}}</div></tr></td><noinclude> |} {{Documentation}} </noinclude> 791822619c27809b308010e9b9fb71720d2f98f0 Template:Starbox observe 10 159 334 333 2022-09-04T15:25:19Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <noinclude>{{Astro talk}} {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude> |- ! style="text-align: center; background-color: #FFFFC0;" colspan="2" | Observation data<br/>{{#ifeq:{{{epoch}}}|[[J2000.0]] ([[International Celestial Reference System|ICRS]])|[[Epoch (astronomy)|Epoch]] [[J2000.0]]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[Equinox (celestial coordinates)|Equinox]] [[J2000.0]] ([[International Celestial Reference System|ICRS]])| [[Epoch (astronomy)|Epoch]] {{{epoch}}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[Equinox (celestial coordinates)|Equinox]] {{{equinox|{{{epoch|}}}}}}}} |- style="vertical-align:top" ! style="text-align:left" | [[Constellation]] | {{{constell}}} |- style="vertical-align:top" {{#if:{{{pronounce<includeonly>|</includeonly>}}}| ! style="text-align:left" {{!}} [[WP:IPA for English|Pronunciation]] {{!}} {{{pronounce}}} }} |- style="vertical-align:top" ! style="text-align:left" | {{nowrap|[[Right ascension]]}} | {{{ra}}} |- style="vertical-align:top" ! style="text-align:left" | [[Declination]] | {{{dec}}} |- style="vertical-align:top" {{#if:{{{appmag_v<includeonly>|</includeonly>}}}| ! style="text-align:left" {{!}} {{nowrap|[[Apparent magnitude|Apparent&nbsp;magnitude]]&nbsp;(V)}} {{!}} {{{appmag_v}}} }}<noinclude> |} {{Documentation}} </noinclude> 21bf36f2041ff2d017e71e8c048693e9ad9e15db Template:Starbox reference 10 160 336 335 2022-09-04T15:25:19Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki <noinclude> {| class="toccolours" style="float: right; clear: right; margin: 0 0 1em 1em; padding: 3px;" </noinclude><tr><th style="background-color: #FFFFC0; text-align: center;" colspan="2">{{#if:{{{no_heading|}}}||Database references}}</th></tr>{{#if:{{{component|}}}|<tr style="text-align:center"><th colspan="2">{{{component}}}</th></tr>}}<!-- -->{{#if:{{{Simbad<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td>'''[[SIMBAD]]'''</td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad}}} {{{sn|data}}}]</tr>}}<!-- -->{{#if:{{{Simbad2<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad2}}} {{{sn2|data2}}}]</tr>}}<!-- -->{{#if:{{{Simbad3<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad3}}} {{{sn3|data3}}}]</tr>}}<!-- -->{{#if:{{{Simbad4<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad4}}} {{{sn4|data4}}}]</tr>}}<!-- -->{{#if:{{{Simbad5<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad5}}} {{{sn5|data5}}}]</tr>}}<!-- -->{{#if:{{{Simbad6<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad6}}} {{{sn6|data6}}}]</tr>}}<!-- -->{{#if:{{{Simbad7<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad7}}} {{{sn7|data7}}}]</tr>}}<!-- -->{{#if:{{{Simbad8<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad8}}} {{{sn8|data8}}}]</tr>}}<!-- -->{{#if:{{{Simbad9<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://simbad.cds.unistra.fr/simbad/sim-id?Ident={{{Simbad9}}} {{{sn9|data9}}}]</tr>}}<!-- -->{{#if:{{{NSTED<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td>'''[[Exoplanet Archive]]'''</td><td>[https://exoplanetarchive.ipac.caltech.edu/cgi-bin/DisplayOverview/nph-DisplayOverview?objname={{{NSTED}}} {{{nn|data}}}]</tr>}}<!-- -->{{#if:{{{NSTED2<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://exoplanetarchive.ipac.caltech.edu/cgi-bin/DisplayOverview/nph-DisplayOverview?objname={{{NSTED2}}} {{{nn2|data2}}}]</tr>}}<!-- -->{{#if:{{{NSTED3<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://exoplanetarchive.ipac.caltech.edu/cgi-bin/DisplayOverview/nph-DisplayOverview?objname={{{NSTED3}}} {{{nn3|data3}}}]</tr>}}<!-- -->{{#if:{{{ARICNS<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td>'''ARICNS'''</td><td>[https://wwwadd.zah.uni-heidelberg.de/datenbanken/aricns/cnspages/4c{{{ARICNS}}}.htm {{{an|data}}}]</td></tr>}}<!-- -->{{#if:{{{ARICNS2<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://wwwadd.zah.uni-heidelberg.de/datenbanken/aricns/cnspages/4c{{{ARICNS2}}}.htm {{{an2|data2}}}]</td></tr>}}<!-- -->{{#if:{{{ARICNS3<includeonly>|</includeonly>}}}|<tr style="vertical-align: top;"><td></td><td>[https://wwwadd.zah.uni-heidelberg.de/datenbanken/aricns/cnspages/4c{{{ARICNS3}}}.htm {{{an3|data3}}}]</td></tr>}}<!-- -->{{#if:{{{EPE<includeonly>|</includeonly>}}}|<tr><td>'''[[Extrasolar Planets Encyclopaedia|Extrasolar Planets<br />Encyclopaedia]]'''</td><td>[https://exoplanet.eu/star.php?st={{{EPE}}} data]</td></tr>}}<!-- -->{{#if:{{{KIC<includeonly>|</includeonly>}}}|<tr><td>'''[[Kepler Input Catalog|KIC]]'''</td><td>[https://archive.stsci.edu/kepler/data_search/search.php?action=Search&ktc_kepler_id={{{KIC}}} data]</td></tr> }}<noinclude> |} {{Documentation}} </noinclude> f84999acae32fc7dacb316605220d28af5b2f06d Template:Carina (constellation) 10 161 338 337 2022-09-04T15:25:20Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{Navbox | name = Carina (constellation) | title = [[Carina (constellation)|Carina constellation]] | bodyclass = hlist | state = {{{state|<noinclude>uncollapsed</noinclude>}}} | group1 = [[Star]]s<br>([[List of stars in Carina|list]]) | list1 = {{Navbox|subgroup | group1 = [[Bayer designation|Bayer]] | list1 = * [[Canopus|α (Canopus)]] * [[Beta Carinae|β (Miaplacidus)]] * [[Epsilon Carinae|ε (Avior)]] * [[Eta Carinae|η]] * [[Theta Carinae|θ]] * [[Iota Carinae|ι (Aspidiske)]] * [[Upsilon Carinae|υ]] * [[Chi Carinae|χ]] * [[Omega Carinae|ω]] | group3 = [[Variable star designation|Variable]] | list3 = * [[R Carinae|R]] * [[HD 88366|S]] * [[T Carinae|T (not variable)]] * [[HD 95109|U]] * [[V Carinae|V]] * [[X Carinae|X]] * [[Y Carinae|Y]] * [[RT Carinae|RT]] * [[UX Carinae|UX]] * [[VY Carinae|VY]] * [[WZ Carinae|WZ]] * [[XY Carinae|XY]] * [[XZ Carinae|XZ]] * [[YZ Carinae|YZ]] * [[AG Carinae|AG]] * [[BO Carinae|BO]] * [[CK Carinae|CK]] * [[CR Carinae|CR]] * [[DW Carinae|DW]] * [[EM Carinae|EM]] * [[EY Carinae|EY]] * [[GG Carinae|GG]] * [[GH Carinae|GH]] * [[GL Carinae|GL]] * [[GZ Carinae|GZ]] * [[HH Carinae|HH]] * [[HR Carinae|HR]] * [[IW Carinae|IW]] * [[IX Carinae|IX]] * [[OY Carinae|OY]] * [[PP Carinae|PP (p)]] * [[QU Carinae|QU]] * [[QX Carinae|QX]] * [[HD 88661|QY]] * [[QZ Carinae|QZ]] * [[V337 Carinae|V337 (q)]] * [[HD 65750|V341]] * [[V343 Carinae|V343 (d)]] * [[V344 Carinae|V344 (f)]] * [[V345 Carinae|V345 (E)]] * [[V348 Carinae|V348]] * [[V357 Carinae|V357 (a)]] * [[HD 92664|V364]] * [[V368 Carinae|V368]] * [[HD 91619|V369]] * [[HD 92207|V370]] * [[HD 96919|V371 (z<sup>2</sup>)]] * [[V372 Carinae|V372]] * [[HD 66194|V374]] * [[V375 Carinae|V375]] * [[V376 Carinae|V376 (b<sup>1</sup>)]] * [[HD 92024|V381]] * [[V382 Carinae|V382 (x)]] * [[V386 Carinae|V386]] * [[V390 Carinae|V390]] * [[V392 Carinae|V392]] * [[HD 90657|V398]] * [[V399 Carinae|V399 (P)]] * [[V403 Carinae|V403]] * [[HD 60435|V409]] * [[HD 96248|V414]] * [[HR 2554|V415 (A)]] * [[HD 94546|V428]] * [[HD 96446|V430]] * [[HD 97152|V431]] * [[V448 Carinae|V448 (O)]] * [[V450 Carinae|V450]] * [[HR 3153|V460]] * [[V461 Carinae|V461]] * [[V469 Carinae|V469]] * [[V473 Carinae|V473]] * [[V478 Carinae|V478]] * [[V482 Carinae|V482]] * [[V486 Carinae|V486]] * [[V487 Carinae|V487]] * [[V492 Carinae|V492]] * [[V495 Carinae|V495]] * [[V507 Carinae|V507]] * [[V514 Carinae|V514]] * [[V518 Carinae|V518]] * [[HD 92964|V519]] * [[V520 Carinae|V520 (w)]] * [[V522 Carinae|V522]] * [[V524 Carinae|V524]] * [[V528 Carinae|V528]] * [[V532 Carinae|V532]] * [[V533 Carinae|V533 (y)]] * [[V535 Carinae|V535]] * [[HD 307938|V557]] * [[HD 93205|V560]] * [[HD 85567|V596]] * [[HD 87643|V640]] * [[V655 Carinae|V655]] * [[V906 Carinae|V906]] | group4 = [[Bright Star Catalogue|HR]] | list4 = * [[HD 44267|2278]] * [[HD 46569|2400]] * [[HD 47001|2416]] * [[N Carinae|2435 (N)]] * [[HD 49517|2515]] * [[HD 49689|2523]] * [[HD 49705|2524]] * [[HD 51210|2592]] * [[HD 52603|2634]] * [[HD 52622|2638]] * [[HD 53047|2652]] * [[HD 53349|2661]] * [[HD 54732|2698]] * [[HD 56239|2754]] * [[HD 56705|2767]] * [[HD 57852|2813]] * [[HD 57917|2815]] * [[HD 59219|2862]] * [[HD 60060|2884]] * [[HD 60228|2892]] * [[HD 61031|2925]] * [[HD 61248|2934 (Q)]] * [[HD 61394|2941]] * [[HD 62758|3006]] * [[HD 62897|3012]] * [[HD 63382|3031]] * [[HD 63926|3056]] * [[HD 64067|3062]] * [[HD 64185|3070]] * [[HD 65189|3100]] * [[HD 65273|3105]] * [[HD 65662|3120]] * [[HD 65867|3133]] * [[HD 65907|3138]] * [[HD 65908|3139]] * [[HD 66341|3152]] * [[HD 66441|3156]] * [[HR 3159|3159 (D)]] * [[HD 66607|3161]] * [[HD 67364|3180]] * [[HD 68423|3217]] * [[HD 68434|3218]] * [[HR 3220|3220 (B)]] * [[HD 69863|3260 (C)]] * [[HD 70267|3274]] * [[HD 70839|3293]] * [[HD 70982|3298]] * [[HD 72322|3368]] * [[HD 73389|3414 (e<sup>2</sup>)]] * [[HD 73390|3415 (e<sup>1</sup>)]] * [[HD 73887|3432]] * [[HD 74148|3443]] * [[HD 74341|3455]] * [[HD 74622|3471]] * [[HD 75086|3489]] * [[HD 76113|3536]] * [[HD 76346|3549]] * [[HD 76538|3560]] * [[HD 76728|3571 (c)]] * [[HD 77370|3598 (b<sup>2</sup>)]] * [[HD 77615|3604]] * [[HD 78293|3622]] * [[HD 78632|3632]] * [[HR 3643|3643 (G)]] * [[HD 79447|3663 (i)]] * [[HD 79698|3673]] * [[HD 80094|3691]] * [[HD 80126|3693]] * [[HD 80230|3696 (g)]] * [[HD 80671|3712]] * [[HD 80951|3720]] * [[HD 80950|3721]] * [[HD 81101|3728 (k)]] * [[HD 81502|3740]] * [[HD 81613|3742]] * [[HD 81830|3752]] * [[HD 82068|3761]] * [[HD 82347|3776]] * [[HD 82350|3777]] * [[HD 82406|3783]] * [[HD 82858|3813]] * [[HD 83095|3821 (H)]] * [[HD 83183|3825 (h)]] * [[HD 83944|3856 (m)]] * [[HD 84121|3863]] * [[HD 84152|3864]] * [[HD 84810|3884 (l)]] * [[HD 84850|3887]] * [[HD 85655|3913]] * [[HD 85656|3914]] * [[HD 86606|3944]] * [[HD 87238|3957]] * [[HD 87283|3960]] * [[HD 87436|3966]] * [[HD 87438|3967]] * [[HD 87543|3971]] * [[HD 88323|3995]] * [[HD 88473|4002]] * [[HD 88825|4018]] * [[HD 88907|4022]] * [[HD 88981|4025 (M)]] * [[HD 89263|4043]] * [[HD 89715|4065]] * [[HD 90264|4089 (L)]] * [[HD 90289|4091]] * [[HD 90454|4095]] * [[HR 4102|4102 (I)]] * [[HD 90630|4105]] * [[HD 90853|4114 (s)]] * [[HD 90874|4115]] * [[HD 91056|4120]] * [[HD 91270|4128]] * [[HR 4138|4138 (K)]] * [[HD 91496|4142]] * [[HD 91533|4144]] * [[HD 91767|4151]] * [[HD 91942|4159 (r)]] * [[HD 92063|4164 (t<sup>1</sup>)]] * [[HD 92397|4177 (t<sup>2</sup>)]] * [[HD 92436|4179]] * [[HD 92682|4186]] * [[HD 93163|4204]] * [[HD 93194|4205]] * [[HD 93344|4211]] * [[HD 93359|4212]] * [[HD 93372|V213]] * [[HD 93502|4217]] * [[HD 93540|4219]] * [[HD 93549|4220]] * [[HD 93607|4222]] * [[HD 93662|4226]] * [[HD 93943|4239]] * [[HD 94510|4257 (u)]] * [[HD 94650|4262]] <!--Search the HR number on SIMBAD for this star--> * [[HD 94683|4266]] * [[HD 95208|4279]] * [[HD 95324|4290]] * [[HD 96544|4323]] * [[HD 96566|4325 (z<sup>1</sup>)]] * [[HD 96568|4326]] * [[HD 96706|4329]] * [[HD 97472|4349]] * [[HD 97583|4355]] * [[HD 97670|4361]] * [[HD 98560|4384]] | group5 = [[Henry Draper Catalogue|HD]] | list5 = * [[HD 49219|49219]] * [[HD 51608|51608]] * [[HD 53143|53143]] * [[HD 54967|54967]] * [[HD 63765|63765]] * [[HD 65216|65216]] * [[HD 79699|79699]] * [[HD 81896|81896]] * [[HD 82458|82458]] * [[HD 84046|84046]] * [[HD 89805|89805]] * [[HD 90074|90074]] * [[HD 90657|90657]] * [[HD 91094|91094]] * [[HD 92399|92399]] * [[HD 92536|92536]] * [[HD 93129A|93129A]] * [[HD 93250|93250]] * [[HD 93403|93403]] * [[HD 93645|93645]] * [[HD 93695|93695]] * [[HD 93738|93738]] * [[HD 93739|93739]] * [[HD 93843|93843]] * [[HD 94275|94275]] * [[HD 94305|94305]] * [[HD 94491|94491]] * [[HD 95086|95086]] * [[HD 95122|95122]] * [[HD 96088|96088]] * [[HD 97950|97950]] * [[HD 98025|98025]] | group6 = [[Gliese catalogue|Gliese]] | list6 = | group7 = Other | list7 = * [[BPM 6502]] * [[CPD−57° 2874]] * [[CPD−59° 2628]] * [[CPD−59° 2635]] * [[DENIS J081730.0−615520|DEN 0817−6155]] * [[AXP 1E 1048-59|1E 1048-59]] * [[FO 15]] * [[He 2-38]] * [[Innes' star]] * [[LHS 288]] * [[NGC 3603-A1]] * [[NGC 3603-B]] * [[NGC 3603-C]] * [[OGLE-TR-111]] * [[OGLE-TR-113]] * [[OGLE-TR-122]] * [[OGLE-TR-123]] * [[OGLE-TR-132]] * [[OGLE-TR-182]] * [[OGLE-TR-211]] * [[OGLE2-TR-L9]] * [[PSR J1048-5832]] * [[PSR J1119-6127]] * [[2S 0921-630]] * [[Sher 25]] * [[SS73 17]] * [[Tr 16-104]] * [[WR 16]] * [[WR 18]] * [[WR 20a]] * [[WR 21a]] * [[WR 22]] * [[WR 23]] * [[WR 24]] * [[WR 25]] * [[WR 30]] * [[WR 30a]] * [[WR 31a]] * [[WR 40]] * [[WR 42e]] * [[AWI0005x3s]] * [[WRA 751]] <!--Simbad ID is V432 Car--> }} |group2 = [[Star cluster|Star<br/>clusters]] |list2 = {{Navbox|subgroup |group1=[[Stellar association|Association]] |list1= * [[Carina OB1]] * [[Carina OB2]] |group2=[[Open cluster|Open]] |list2= * [[Collinder 228]] * [[IC 2602]] * [[IC 2714]] * [[NGC 2516]] * [[NGC 2609]] * [[NGC 3036]] * [[NGC 3114]] * [[NGC 3247]] * [[NGC 3255]] * [[NGC 3293]] * [[NGC 3324]] * [[NGC 3496]] * [[NGC 3519]] * [[NGC 3532]] * [[NGC 3572]] * [[NGC 3590]] * [[NGC 3603]] * [[Trumpler 14]] * [[Trumpler 15]] * [[Trumpler 16]] * [[Westerlund 2]] |group3=[[Globular cluster|Globular]] |list3= * [[NGC 2808]] }} |group3 = [[Nebula]]e |list3= {{Navbox|subgroup |group1=[[H II region|H II]] |list1= * [[Carina Nebula]] * [[NGC 3199]] * [[NGC 3576]] * [[NGC 3579]] * [[NGC 3581]] * [[NGC 3582]] * [[NGC 3584]] * [[NGC 3586]] * [[RCW 49]] |group2=[[Reflection nebula|Reflection]] |list2= * [[Homunculus Nebula]] * [[IC 2220]] * [[NGC 3503]] |group3=[[Planetary nebula|Planetary]] |list3= * [[He 2-36]] * [[Hen 2-47]] * [[IC 2448]] * [[IC 2501]] * [[IC 2553]] * [[NGC 2867]] * [[NGC 3211]] |group4=[[Supernova remnant|SNR]] |list4= * [[G290.1-0.8]] |group5=[[Pulsar wind nebula|Pulsar wind]] |list5= * [[IGR J11014−6103]] }} |group4 = [[Galaxy|Galaxies]] |list4= {{Navbox|subgroup |group1=[[Messier object|Messier]] |list1= |group2=[[New General Catalogue|NGC]] |list2= * [[NGC 2191|2191]] * [[NGC 2369|2369]] * [[NGC 2369A|2369A]] * [[NGC 2369B|2369B]] * [[NGC 2381|2381]] * [[NGC 2417|2417]] * [[NGC 2502|2502]] * [[NGC 2640|2640]] * [[NGC 2714|2714]] * [[NGC 2788|2788]] * [[NGC 2822|2822]] * [[NGC 2836|2836]] * [[NGC 2842|2842]] * [[NGC 2887|2887]] * [[NGC 3059|3059]] * [[NGC 3136|3136]] * [[NGC 3136A|3136A]] * [[NGC 3136B|3136B]] |group3=Other |list3= * [[Carina Dwarf Spheroidal Galaxy]] }} |group5=[[Galaxy cluster|Galaxy<br/>clusters]] |list5= * [[Abell 3391]] * [[Abell 3395]] * [[Bullet Cluster]] |group6=Other |list6= * [[GRB 000131]] * [[GRB 080916C]] }}<noinclude> == Documentation == {{Universe navboxes}} [[Category:Stars of constellation templates|Carina]] </noinclude> b3e9a604f6e67f2ecee2dbda375f4d9ba3b2bc17 Template:Cite DR2 10 162 340 339 2022-09-04T15:25:20Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki #REDIRECT [[Template:Cite Gaia DR2]] {{R from move}} f105cdaa4ffd5d7683d35297a855d5e4fc5c1c16 Template:Cite Gaia DR2 10 163 342 341 2022-09-04T15:25:20Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{cite journal | last1=Brown | first1=A. G. A. | display-authors=etal | collaboration=Gaia collaboration | date=August 2018 | title=''Gaia'' Data Release 2: Summary of the contents and survey properties | journal=[[Astronomy & Astrophysics]] | volume=616 |at=A1 | arxiv=1804.09365 | bibcode=2018A&A...616A...1G | bibcode-access=free | doi=10.1051/0004-6361/201833051 | doi-access=free | mode={{{mode|}}} }}{{#if:{{{1|}}}|&#32;[http://vizier.u-strasbg.fr/viz-bin/VizieR-S?Gaia%20DR2%20{{Trim|{{{1|}}}}} Gaia DR2 record for this source] at [[VizieR]].}}<noinclude> {{Documentation}} </noinclude> f0d86754ae543ff75617b1a118b720534de42335 Template:Odlist 10 164 344 343 2022-09-04T15:25:21Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{comma separated entries <!-- Traditional/proper names, or exoplanet star designations --> | {{{name<includeonly>|</includeonly>}}} | {{{name2<includeonly>|</includeonly>}}} | {{{name3<includeonly>|</includeonly>}}} | {{{name4<includeonly>|</includeonly>}}} | {{{name5<includeonly>|</includeonly>}}} <!-- Bayer, Flamsteed, Gould, and variable star designations --> | {{#if:{{{B|}}} |[[Bayer designation|{{{B}}}]]}} | {{#if:{{{F|}}} |[[Flamsteed designation|{{{F}}}]]}} | {{#if:{{{Gould|}}}|[[Gould designation|{{{Gould}}}]]}} | {{#if:{{{V|}}} |[[Variable star designation|{{{V}}}]]}} | {{#if:{{{NSV|}}} |[[New Catalogue of Suspected Variable Stars|NSV]]&nbsp;{{{NSV}}}}} <!-- Commonly used designations like HD, HIP, HR --> | {{#if:{{{AG|}}} |{{nowrap|[[Astronomische Gesellschaft Katalog|AG]]{{Str rep|{{{AG}}}|-|−}}}}}} | {{#if:{{{BD<includeonly>|</includeonly>}}} |{{nowrap|[[Bonner Durchmusterung|BD]]{{Str rep|{{{BD}}}|-|−}}}}}} | {{#if:{{{CD|}}} |{{nowrap|[[Cordoba Durchmusterung|CD]]{{Str rep|{{{CD}}}|-|−}}}}}} | {{#if:{{{CP|}}} |{{nowrap|[[Cape Photographic Durchmusterung|CPD]]{{Str rep|{{{CP}}}|-|−}}}}}} | {{#if:{{{CPD|}}} |{{nowrap|[[Cape Photographic Durchmusterung|CPD]]{{Str rep|{{{CPD}}}|-|−}}}}}} | {{#if:{{{FK5|}}} |[[Fifth Fundamental Catalogue|FK5]]&nbsp;{{{FK5}}}}} | {{#if:{{{Gaia DR1|}}} |{{nowrap|[[Star_catalogue#Gaia_Catalogue|Gaia DR1]]&nbsp;{{{Gaia DR1}}}}}}} | {{#if:{{{Gaia DR2|}}} |{{nowrap|[[Star_catalogue#Gaia_Catalogue|Gaia DR2]]&nbsp;{{{Gaia DR2}}}}}}} | {{#if:{{{GC|}}} |[[Boss General Catalogue|GC]]&nbsp;{{{GC}}}}} | {{#if:{{{GJ<includeonly>|</includeonly>}}} |[[Gliese Catalogue of Nearby Stars|GJ]]&nbsp;{{{GJ}}}}} | {{#if:{{{GJ2<includeonly>|</includeonly>}}} |GJ&nbsp;{{{GJ2}}}}} | {{#if:{{{HD<includeonly>|</includeonly>}}} |[[Henry Draper Catalogue|HD]]&nbsp;{{{HD}}}}} | {{#if:{{{HIP<includeonly>|</includeonly>}}} |[[Hipparcos Catalogue|HIP]]&nbsp;{{{HIP}}}}} | {{#if:{{{HR<includeonly>|</includeonly>}}} |[[Harvard Revised catalogue|HR]]&nbsp;{{{HR}}}}} | {{#if:{{{SAO<includeonly>|</includeonly>}}} |[[Smithsonian Astrophysical Observatory Star Catalog|SAO]]&nbsp;{{{SAO}}}}} | {{#if:{{{PPM|}}} |[[Position and proper motion catalogue|PPM]]&nbsp;{{{PPM}}}}} <!-- Double star catalogs --> | {{#if:{{{ADS|}}} |[[Aitken Double Star Catalogue|ADS]]&nbsp;{{{ADS}}}}} | {{#if:{{{CCDM|}}} |{{nowrap|[[Catalog of Components of Double and Multiple Stars|CCDM]] {{{CCDM}}}}}}} | {{#if:{{{WDS<includeonly>|</includeonly>}}} |{{nowrap|[[Washington Double Star Catalog|WDS]] {{{WDS}}}}}}} | {{#if:{{{DC|}}} |[[Discovery code|{{{DC}}}]]}} <!-- Nearby/high-proper-motion star catalogues and the like--> | {{#if:{{{AC|}}} |[[Carte du Ciel|AC]]&nbsp;{{{AC}}}}} | {{#if:{{{BPM|}}} |[[Bruce Proper Motion survey|BPM]]&nbsp;{{{BPM}}}}} | {{#if:{{{Ci 18|}}}|[[Cincinnati Observatory|Ci]]&nbsp;18&nbsp;{{{Ci 18}}}}} | {{#if:{{{Ci 20|}}}|[[Cincinnati Observatory|Ci]]&nbsp;20&nbsp;{{{Ci 20}}}}} | {{#if:{{{EGGR|}}} |[[Olin J. Eggen|EG]][[Jesse L. Greenstein|GR]]&nbsp;{{{EGGR}}}}} | {{#if:{{{G|}}} |{{nowrap|[[Henry L. Giclas catalogue|G]] {{{G}}}}}}} | {{#if:{{{G2|}}} |{{nowrap|[[Henry L. Giclas catalogue|G]] {{{G2}}}}}}} | {{#if:{{{G3|}}} |{{nowrap|[[Henry L. Giclas catalogue|G]] {{{G3}}}}}}} | {{#if:{{{L|}}} |[[Luyten|L]]&nbsp;{{{L}}}}} | {{#if:{{{LAL|}}} |[[Histoire céleste française|LAL]]&nbsp;{{{LAL}}}}} | {{#if:{{{LAWD|}}} |[[Luyten Atlas of White Dwarfs|LAWD]]&nbsp;{{{LAWD}}}}} | {{#if:{{{LFT|}}} |[[Luyten Five-Tenths catalogue|LFT]]&nbsp;{{{LFT}}}}} | {{#if:{{{LHS|}}} |[[Luyten Half-Second Catalogue|LHS]]&nbsp;{{{LHS}}}}} | {{#if:{{{LP|}}} |[[Luyten-Palomar proper motion catalogue|LP]]&nbsp;{{{LP}}}}} | {{#if:{{{LPM|}}} |[[Luyten Proper-Motion Catalogue|LPM]]&nbsp;{{{LPM}}}}} | {{#if:{{{LSPM|}}} |{{nowrap|[[LSPM-North Catalog|LSPM]] {{{LSPM}}}}}}} | {{#if:{{{LTT|}}} |[[Luyten Two-Tenths catalogue|LTT]]&nbsp;{{{LTT}}}}} | {{#if:{{{NLTT|}}} |[[NLTT]]&nbsp;{{{NLTT}}}}} | {{#if:{{{PLX|}}} |[[General Catalogue of Trigonometric Parallaxes|PLX]]&nbsp;{{{PLX}}}}} | {{#if:{{{PM|}}} |[[Proper motion|PM]]&nbsp;{{{PM}}}}} | {{#if:{{{PM2|}}} |[[Proper motion|PM]]&nbsp;{{{PM2}}}}} | {{#if:{{{Ross|}}} |[[Ross catalogue|Ross]]&nbsp;{{{Ross}}}}} | {{#if:{{{SCR|}}} |{{nowrap|[[Super-COSMOS RECONS|SCR]]&nbsp;{{{SCR}}}}}}} | {{#if:{{{WD|}}} |{{nowrap|[[White dwarf|WD]]&nbsp;{{{WD}}}}}}} | {{#if:{{{WD2|}}} |{{nowrap|[[White dwarf|WD]]&nbsp;{{{WD2}}}}}}} | {{#if:{{{WD3|}}} |{{nowrap|[[White dwarf|WD]]&nbsp;{{{WD3}}}}}}} | {{#if:{{{Wolf|}}} |[[Max Wolf|Wolf]]&nbsp;{{{Wolf}}}}} <!-- Exoplanet surveys --> | {{#if:{{{Kepler|}}} |{{nowrap|[[Kepler space telescope|Kepler]]-{{{Kepler}}}}}}} | {{#if:{{{KOI|}}} |{{nowrap|[[Kepler object of interest|KOI]]-{{{KOI}}}}}}} | {{#if:{{{KIC|}}} |{{nowrap|[[Kepler Input Catalog|KIC]]&nbsp;{{{KIC}}}}}}} | {{#if:{{{EPIC|}}} |{{nowrap|[[Ecliptic Plane Input Catalog|EPIC]]&nbsp;{{{EPIC}}}}}}} | {{#if:{{{TOI|}}} |{{nowrap|[[Tess object of interest|TOI]]-{{{TOI}}}}}}} | {{#if:{{{TIC|}}} |{{nowrap|[[TESS Input Catalog|TIC]]&nbsp;{{{TIC}}}}}}} <!-- Extensive star surveys --> | {{#if:{{{TYC|}}} |{{nowrap|[[Tycho Catalogue|TYC]]&nbsp;{{{TYC}}}}}}} | {{#if:{{{GCRV|}}} |{{nowrap|[[GCRV]]&nbsp;{{{GCRV}}}}}}} | {{#if:{{{GSC|}}} |{{nowrap|[[Guide Star Catalog|GSC]]&nbsp;{{{GSC}}}}}}} | {{#if:{{{IRAS|}}} |{{nowrap|[[IRAS]] {{{IRAS}}}}}}} | {{#if:{{{2MASS|}}}|{{nowrap|[[2MASS]] {{{2MASS}}}}}}} | {{#if:{{{2MASX|}}}|{{nowrap|[[2MASX]] {{{2MASX}}}}}}} | {{#if:{{{DENIS|}}}|{{nowrap|[[DENIS]] {{{DENIS}}}}}}} | {{#if:{{{WISE|}}} |{{nowrap|[[Wide-field Infrared Survey Explorer|WISE]] {{{WISE}}}}}}} | {{#if:{{{WISEA|}}}|{{nowrap|[[Wide-field Infrared Survey Explorer|WISEA]] {{{WISEA}}}}}}} <!-- Galaxy catalogs --> | {{#if:{{{NGC|}}} |{{nowrap|[[New General Catalogue|NGC]] {{{NGC}}}}}}} | {{#if:{{{IC|}}} |{{nowrap|[[Index Catalogue|IC]] {{{IC}}}}}}} | {{#if:{{{Arp|}}} |{{nowrap|[[Atlas of Peculiar Galaxies|Arp]] {{{Arp}}}}}}} | {{#if:{{{UGC|}}} |{{nowrap|[[Uppsala General Catalogue|UGC]] {{{UGC}}}}}}} | {{#if:{{{UGCA|}}} |{{nowrap|[[UGCA]] {{{UGCA}}}}}}} | {{#if:{{{LEDA|}}} |{{nowrap|[[Lyon-Meudon Extragalactic Database|LEDA]] {{{LEDA}}}}}}} | {{#if:{{{MCG|}}} |{{nowrap|[[Morphological Catalogue of Galaxies|MCG]] {{{MCG}}}}}}} | {{#if:{{{MRK|}}} |{{nowrap|[[Markarian galaxies|Mrk]] {{{MRK}}}}}}} | {{#if:{{{PGC|}}} |{{nowrap|[[Principal Galaxies Catalogue|PGC]] {{{PGC}}}}}}} | {{#if:{{{CGCG|}}} |{{nowrap|[[Catalogue of Galaxies and of Clusters of Galaxies|CGCG]] {{{CGCG}}}}}}} | {{#if:{{{VV|}}} |{{nowrap|[[Vorontsov-Vel'yaminov Interacting Galaxies|VV]] {{{VV}}}}}}} | {{#if:{{{KPG|}}} |KPG&nbsp;{{{KPG}}}}} | {{#if:{{{SDSS|}}} |{{nowrap|[[Sloan Digital Sky Survey|SDSS]] {{{SDSS}}}}}}} }}<noinclude> {{documentation|content= This template may be used to create a list of other designations within [[Template:Starbox catalog]] or [[Template:Infobox galaxy]]. == Usage == A blank template with all the possible parameters is given below. You may delete any unused parameters. <pre> {{odlist | name = | name2 = | name3 = | name4 = | name5 = | 2MASS = <!-- Two Micron All-Sky Survey --> | AC = <!-- Carte du Ciel --> | AG = <!-- Astronomische Gesellschaft Katalog --> | ADS = <!-- Aitken Double Star Catalogue --> | B = <!-- Bayer designation --> | BD = <!-- Bonner Durchmusterung --> | BPM = <!-- Bruce Proper Motion survey --> | CCDM = <!-- Catalogue of Components of Double and Multiple Stars --> | CD = <!-- Cordoba Durchmusterung --> | Ci 18 = <!-- Cincinnati Observatory --> | Ci 20 = <!-- Cincinnati Observatory --> | CP = <!-- Cape Photographic Durchmusterung --> | CPD = <!-- Cape Photographic Durchmusterung --> | DC = <!-- Washington Double Star Catalog discovery code (see WDS) --> | DENIS = <!-- Deep Near Infrared Survey of the Southern Sky --> | EGGR = <!-- Olin J. Eggen --> | EPIC = <!-- Ecliptic Plane Input Catalog --> | F = <!-- Flamsteed designation --> | FK5 = <!-- Fifth Fundamental Catalogue --> | G = <!-- Henry L. Giclas catalogue --> | G2 = <!-- Henry L. Giclas catalogue --> | G3 = <!-- Henry L. Giclas catalogue --> | Gaia DR1 = <!-- Gaia data release 1 --> | Gaia DR2 = <!-- Gaia data release 2 --> | GCRV = <!-- General Catalogue of Stellar Radial Velocities --> | GJ = <!-- Gliese-Jahreiss catalogue --> | GJ2 = <!-- Gliese-Jahreiss catalogue --> | Gould = <!-- Uranometria Argentina catalogue --> | GSC = <!-- Guide Star Catalog --> | HD = <!-- Henry Draper Catalogue --> | HIP = <!-- Hipparcos Catalogue --> | HR = <!-- Harvard Revised catalogue --> | IRAS = <!-- Infrared Astronomical Satellite --> | Kepler = <!-- Kepler --> | KIC = <!-- Kepler Input Catalogue --> | KOI = <!-- Kepler Object of Interest --> | L = <!-- Luyten --> | LAL = <!-- Histoire céleste française --> | LAWD = <!-- Luyten Atlas of White Dwarfs --> | LDS = <!-- Luyten Double Stars catalogue --> | LP = <!-- Luyten-Palomar proper motion catalogue --> | LPM = <!-- Luyten Proper-Motion Catalogue --> | LFT = <!-- Luyten Five-Tenths catalogue --> | LHS = <!-- Luyten Half-Second Catalogue --> | LSPM = <!-- LSPM-North Catalog --> | LTT = <!-- Luyten Two-Tenths catalogue --> | NLTT = <!-- New Luyten Two-Tenths Catalogue --> | NSV = <!-- New Catalogue of Suspected Variable Stars --> | PLX = <!-- General Catalogue of Trigonometric Parallaxes --> | PM = <!-- Proper motion --> | PM2 = <!-- Proper motion --> | PPM = <!-- Position and proper motion catalogue --> | Ross = <!-- Ross catalogue --> | SAO = <!-- Smithsonian Astrophysical Observatory Star Catalogue --> | SCR = <!-- Super-COSMOS RECONS --> | TOI = <!-- Tess Object of Interest --> | TYC = <!-- Tycho Catalogue --> | V = <!-- Variable star designation --> | WD = <!-- White dwarf --> | WD2 = <!-- White dwarf --> | WD3 = <!-- White dwarf --> | WDS = <!-- Washington Double Star Catalog --> | WISE = <!-- Wide-field Infrared Survey Explorer --> | WISEA = <!-- Wide-field Infrared Survey Explorer - All-Sky --> | Wolf = <!-- Max Wolf --> }}</pre> For galaxies, use this one: <pre> {{odlist | name = | name2 = | name3 = | name4 = | name5 = | Arp = <!-- Atlas of Peculiar Galaxies --> | IC = <!-- Index Catalogue --> | LEDA = <!-- Lyon-Meudon Extragalactic Database --> | MCG = <!-- Morphological Catalogue of Galaxies --> | MRK = <!-- Markarian galaxies --> | NGC = <!-- New General Catalogue --> | PGC = <!-- Principal Galaxies Catalogue --> | UGC = <!-- Uppsala General Catalogue --> | UGCA = <!-- Uppsala General Catalogue Addendum --> | 2MASS = <!-- Two Micron All-Sky Survey --> | 2MASX = <!-- Two Micron All-Sky Survey Extended Source Catalog --> | CGCG = <!-- Catalogue of Galaxies and of Clusters of Galaxies --> | VV = <!-- Vorontsov-Vel'yaminov Interacting Galaxies --> | KPG = <!-- Karachentsev Catalogue of Isolated Pairs of Galaxies --> | SDSS = <!-- Sloan Digital Sky Survey --> }}</pre> [[Category:Astronomy templates]] }}</noinclude> a5bf09051821f2310a8126a5829dc0cbd7e51dd9 Template:Cite simbad 10 165 346 345 2022-09-04T15:25:21Z SpaceMan 2 1 revision imported: Canopus wikitext text/x-wiki {{cite web |title={{{title|<noinclude>Title</noinclude>}}} |url=http://simbad.u-strasbg.fr/simbad/sim-basic?Ident{{=}}{{urlencode:{{{title|HD 20794}}}}} |work=[[SIMBAD]] |publisher=[[Centre de données astronomiques de Strasbourg]] |access-date={{{access-date|{{{accessdate|}}}}}} |mode={{{mode|}}} |postscript={{{postscript|}}} }}<noinclude> {{documentation}} </noinclude> b219ca85a3c3d762999e98b05adb0b273a17f2b5 Template:Sky/styles.css 10 166 348 347 2022-09-04T15:25:21Z SpaceMan 2 1 revision imported: Canopus text text/plain /* {{pp-template}} */ /* Similiar to [[Template:Coord]] styling */ .sky-coordinates-display { line-height: 1.5em; text-align: right; text-indent: 0; text-transform: none; white-space: nowrap; } body.skin-vector-legacy .sky-coordinates-display { font-size: 85%; } fb0dd75a941049acd566292c9241b00d7088d099 Canopus 0 37 349 90 2022-09-04T15:28:19Z SpaceMan 2 /* External links */ wikitext text/x-wiki {{short description|Bright giant star in the constellation of Carina}} {{Other uses}} {{Starbox begin | name=Canopus }} {{Starbox image | image=[[File:Canopus.jpg|255px]] | caption=An image of Canopus by [[Expedition 6]] }} {{Starbox observe | epoch=J2000 | constell=[[Carina (constellation)|Carina]] | pronounce={{IPAc-en|k|ə|ˈ|n|oʊ|p|ə|s}}<ref>{{OED|Canopus}}</ref> | ra={{RA|06|23|57.10988}}<ref name="van Leeuwen2007">{{cite journal | title=Validation of the new Hipparcos reduction | last1=van Leeuwen | first1=F. | journal=Astronomy and Astrophysics | volume=474 | issue=2 | pages=653–664 | date=2007 | arxiv=0708.1752 | bibcode=2007A&A...474..653V | doi=10.1051/0004-6361:20078357 | s2cid=18759600 }} [http://webviz.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b48255b3&-out.add=.&-source=I/311/hip2&recno=30362 Vizier catalog entry ]</ref> | dec={{DEC|-52|41|44.3810}}<ref name="van Leeuwen2007"/> | appmag_v=−0.74<ref name="Ducati 2002">{{cite journal | title=Catalogue of Stellar Photometry in Johnson's 11-color system | last1=Ducati | first1=J. R. | journal=CDS/ADC Collection of Electronic Catalogues | volume=2237 | pages=0 | date=2002 | bibcode=2002yCat.2237....0D }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b360304a&-out.add=.&-source=II/237/colors&recno=1155 Vizier catalog entry ]</ref> }} {{Starbox character | type= | class=A9&nbsp;II<ref name=perkins>{{cite journal|bibcode=1989ApJS...69..301G|title=The early F-type stars – Refined classification, confrontation with Stromgren photometry, and the effects of rotation|journal=Astrophysical Journal Supplement Series|volume=69|pages=301|last1=Gray|first1=R. O.|last2=Garrison|first2=R. F.|year=1989|doi=10.1086/191315}}</ref><ref>{{cite journal|bibcode=1993ASPC...45...59L|title=A Spectroscopic Study of High Galactic Latitude F Supergiant Stars|journal=Luminous High-Latitude Stars. The International Workshop on Luminous High-Latitude Stars|volume=45|pages=59|last1=Lopez-Cruz|first1=O.|last2=Garrison|first2=R. F.|year=1993}}</ref> | b-v=+0.15<ref name="Ducati 2002"/> | u-b=+0.10<ref name="Ducati 2002"/> | variable= }} {{Starbox astrometry | radial_v={{val|20.3|0.5}}<ref name="Gontcharov 2007">{{cite journal | title=Pullkovo Compilation of Radial Velocities for 39495 Hipparcos stars in a common system | last1=Gontcharov | first1=G. A. | journal=Astronomy Letters | volume=32 | issue=1 | pages=759–771 | date=2007 | bibcode=2006AstL...32..759G | doi=10.1134/S1063773706110065|arxiv = 1606.08053 | s2cid=119231169 }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b5f60fbd&-out.add=.&-source=III/252/table8&recno=9232 Vizier catalog entry ]</ref> | prop_mo_ra=19.93<ref name="van Leeuwen2007"/> | prop_mo_dec=23.24<ref name="van Leeuwen2007"/> | parallax=10.55 | p_error=0.56 | parallax_footnote=<ref name="van Leeuwen2007"/> | absmag_v=–5.71<ref name=smiljanic2006/> |arxiv = 1606.08053 }} {{Starbox detail | metal_fe=–0.07<ref name=smiljanic2006/> | mass={{Val|8.0|0.3}}<ref name=vlti>{{cite journal|bibcode=2013MNRAS.434..437C|arxiv=1306.3288|title=Fundamental parameters of 16 late-type stars derived from their angular diameter measured with VLTI/AMBER|journal=Monthly Notices of the Royal Astronomical Society|volume=434|issue=1|pages=437–450|last1=Cruzalèbes|first1=P.|last2=Jorissen|first2=A.|last3=Rabbia|first3=Y.|last4=Sacuto|first4=S.|last5=Chiavassa|first5=A.|last6=Pasquato|first6=E.|last7=Plez|first7=B.|last8=Eriksson|first8=K.|last9=Spang|first9=A.|last10=Chesneau|first10=O.|year=2013|doi=10.1093/mnras/stt1037|s2cid=49573767}}</ref>&nbsp;(2013)<br/>{{val|10.1|0.1}}<ref name=Tetzlaff2011/>&nbsp;(2011) | radius={{Val|71|4}}<ref name=vlti/>&nbsp;(2013)<br>{{val|73.3|5.2}}<ref name=DomicianoDeSouza>{{cite journal|doi=10.1051/0004-6361/202140478|title=Refined fundamental parameters of Canopus from combined near-IR interferometry and spectral energy distribution|year=2021|last1=Domiciano De Souza|first1=A.|last2=Zorec|first2=J.|last3=Millour|first3=F.|last4=Le Bouquin|first4=J.-B.|last5=Spang|first5=A.|last6=Vakili|first6=F.|journal=Astronomy & Astrophysics|volume=654|pages=A19|arxiv=2109.07153|bibcode=2021A&A...654A..19D|s2cid=237513623}}</ref>&nbsp;(2021) | gravity={{Val|1.70|0.05}}<ref name=DomicianoDeSouza/> | rotational_velocity=9<ref name=ayres2018/> | rotation={{val|298|u=days|p=≥}}<ref name=Testa2004/> | luminosity=10,700<ref name=vlti/> | temperature=7,400<ref name=ayres2018>{{cite journal |bibcode=2018ApJ...854...95A |title=Cracking the Conundrum of F-supergiant Coronae |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |year=2018 |volume=854 |issue=2 |page=95 |doi=10.3847/1538-4357/aaa6d7 |arxiv=1802.02552 |s2cid=119101035 }}</ref> | age_myr = {{val|25.1|2.5}}<ref name=Tetzlaff2011>{{cite journal | title=A catalogue of young runaway Hipparcos stars within 3 kpc from the Sun | last1=Tetzlaff | first1=N. | last2=Neuhäuser | first2=R. | last3=Hohle | first3=M. M. | journal=Monthly Notices of the Royal Astronomical Society | volume=410 | issue=1 | pages=190–200 | date=January 2011 | doi=10.1111/j.1365-2966.2010.17434.x | arxiv=1007.4883 | bibcode=2011MNRAS.410..190T | s2cid=118629873 }}</ref> }} {{Starbox catalog | names={{odlist | name=Suhayl | name2=Suhel | name3=Suhail | B=α Carinae | CPD=−52°1941 | FK5=245 | HD=45348 | HIP=30438 | HR=2326 | SAO=234480| GC=8302 }}<ref name=SIMBAD>{{cite simbad | title=alf Car | access-date=2019-03-09 }}</ref> }} {{Starbox reference | Simbad=canopus }} {{Starbox end}} '''Canopus''' is the brightest star in the southern [[constellation]] of [[Carina (constellation)|Carina]] and the [[list of brightest stars|second-brightest star]] in the [[night sky]]. It is also [[Bayer designation|designated]] '''α&nbsp;Carinae''', which is [[Latinisation of names|Latinised]] to '''Alpha&nbsp;Carinae'''. With a [[visual apparent magnitude]] of −0.74, it is outshone only by [[Sirius]]. Located around {{val|310|ul=light-years}} from the [[Sun]], Canopus is a [[bright giant]] of [[spectral type A9]], so it is essentially white when seen with the naked eye. It has a luminosity over 10,000 times the [[luminosity of the Sun]], is eight times as [[mass of the Sun|massive]], and has expanded to 71 times the [[Sun's radius]]. Its enlarged [[photosphere]] has an [[effective temperature]] of around {{val|7,400|fmt=commas|u=K}}. Canopus is undergoing [[stellar core|core]] [[helium fusion|helium burning]] and is currently in the so-called [[blue loop]] phase of its [[stellar evolution|evolution]], having already passed through the [[red-giant branch]] after exhausting the hydrogen in its core. Canopus is a [[X-ray astronomy|source of X-rays]], which are likely being emitted from its [[stellar corona|corona]]. The prominent appearance of Canopus means it has been the subject of mythological lore among many ancient peoples. Its proper name is generally considered to originate from the [[Greek mythology|mythological]] [[Canopus (mythology)|Canopus]], who was a navigator for [[Menelaus]], king of [[Sparta]]. The [[acronychal rising]] marked the date of the Ptolemaia festival in Egypt. In ancient India, it was named [[Agastya]] after the revered [[Vedas|Vedic]] sage. For Chinese astronomers, it was known as the [[Old Man of the South Pole]]. ==Nomenclature== The name ''Canopus'' is a Latinisation of the [[Ancient Greek]] name Κάνωβος/Kanôbos, recorded in Claudius Ptolemy's ''[[Almagest]]'' (c.150 AD). Eratosthenes used the same spelling.<ref name="ridpathCr"/> Hipparchos wrote it as Κάνωπος. [[John Flamsteed]] wrote Canobus,<ref>{{cite book|last=Flamsteed|first=John|title=Atlas coelestis|location=London, United Kingdom|date=1729|pages=Constellation Map of Southern Hemisphere|url=http://lhldigital.lindahall.org/u?/astro_atlas,1191}}</ref> as did [[Edmond Halley]] in his 1679 ''Catalogus Stellarum Australium''.<ref name="Halley 1679">{{cite book|last=Halley|first=Edmond|title=Catalogus stellarum australium; sive, Supplementum catalogi Tychenici, exhibens longitudines et latitudines stellarum fixarum, quae, prope polum Antarcticum sitae, in horizonte Uraniburgico Tychoni inconspicuae fuere, accurato calculo ex distantiis supputatas, & ad annum 1677 completum correctas...Accedit appendicula de rebus quibusdam astronomicis|publisher=T. James|location=London|date=1679|pages=30|url=http://babel.hathitrust.org/cgi/pt?id=mdp.39015007000170;view=1up;seq=41;size=150}}</ref> The name has two possible derivations, both listed in [[Richard Hinckley Allen]]'s seminal ''[[Star Names: Their Lore and Meaning]]''. * [[Argo Navis]] was the ship used by [[Jason]] and the Argonauts in the legend of the [[Trojan War]]. The brightest star in the constellation was given the name of a ship's pilot from another Greek legend: [[Canopus (mythology)|Canopus]], pilot of [[Menelaus]]' ship on his quest to retrieve [[Helen of Troy]] after she was taken by [[Paris (mythology)|Paris]].<ref name="hinkley63">{{cite book|first=Richard Hinckley|last=Allen|author-link=Richard Hinckley Allen|date=1963|orig-year=1899|title=Star Names: Their Lore and Meaning|pages=[https://archive.org/details/starnamestheirlo00alle/page/67 67–72]|edition=Revised|publisher=Dover Publications|location=New York|isbn=0-486-21079-0|url-access=registration|url=https://archive.org/details/starnamestheirlo00alle/page/67}}</ref> * A ruined ancient Egyptian port named [[Canopus, Egypt|Canopus]] lies near the mouth of the [[Nile]], site of the [[Battle of the Nile]]. It is speculated that its name is derived from the Egyptian [[Coptic language|Coptic]] ''Kahi Nub'' ("Golden Earth"), which refers to how Canopus would have appeared near the horizon in [[ancient Egypt]], reddened by atmospheric extinction from that position.<ref name="hinkley63"/><ref name=lynn1905>{{cite journal |bibcode=1905Obs....28..289L |title=The brightest fixed star and its name |last1=Lynn |first1=W. T. |journal=The Observatory |year=1905 |volume=28 |page=289 }}</ref> In 2016, the [[International Astronomical Union]] organized a [[IAU Working Group on Star Names|Working Group on Star Names]] (WGSN) to catalog and standardize proper names for stars.<ref name="WGSN">{{cite web | url=https://www.iau.org/science/scientific_bodies/working_groups/280/ | title=IAU Working Group on Star Names (WGSN) | website=iau.org | publisher=[[International Astronomical Union]] | access-date=22 May 2016}}</ref> The WGSN's first bulletin of July 2016 included a table of the first two batches of names approved by the WGSN, which included ''Canopus'' for this star.<ref name="WGSN1">{{cite web | url=https://www.iau.org/static/science/scientific_bodies/working_groups/280/WGSN_bulletin1.pdf | title=Bulletin of the IAU Working Group on Star Names, No. 1 | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06 }}</ref> Canopus is now included in the ''IAU Catalog of Star Names''.<ref name="IAU-CSN">{{cite web | url=https://www.iau.org/public/themes/naming_stars/ | title=IAU Catalog of Star Names | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06}}</ref> Canopus traditionally marked the rudder of the ship [[Argo Navis]].<ref>{{cite journal | title = On Frederick de Houtman's Catalogue of Southern Stars, and the Origin of the Southern Constellations | last1= Knobel|first1=E. B. |journal = [[Monthly Notices of the Royal Astronomical Society]] | volume= 77| issue= 5 | pages=414–432 [422] | bibcode = 1917MNRAS..77..414K |date=1917 | doi=10.1093/mnras/77.5.414| doi-access=free }}</ref> German celestial cartographer [[Johann Bayer]] gave it—as the brightest star in the constellation—the [[Bayer designation|designation]] of ''α&nbsp;Argus'' ([[Latinisation of names|Latinised]] to ''Alpha Argus'') in 1603. In 1763, French astronomer [[Nicolas Louis de Lacaille]] divided the huge constellation into three smaller ones,<ref name=Glass2012>{{cite book | title=Nicolas-Louis De La Caille, Astronomer and Geodesist | first=Ian Stewart | last=Glass | date=November 17, 2012 | page=73 | isbn=9780191649608 | publisher=OUP Oxford | url=https://www.google.com/books/edition/Nicolas_Louis_De_La_Caille_Astronomer_an/eZjlHAIBeRAC?hl=en&gbpv=1&pg=PT73 }}</ref> and hence Canopus became ''α&nbsp;Carinae'' ([[Latinisation of names|Latinised]] to ''Alpha Carinae''). It is listed in the [[Bright Star Catalogue]] as HR 2326, the [[Henry Draper Catalogue]] as HD 45348, and the [[Hipparcos catalogue]] as HIP 30438.<ref name=SIMBAD/> Flamsteed did not number this southern star, but [[Benjamin Apthorp Gould]] gave it the number 7 (7 G. Carinae) in his ''Uranometria Argentina''.<ref name=Gould1878>{{cite journal | title=Uranometria Argentina: Brightness and position of every fixed star, down to the seventh magnitude, within one hundred degrees of the South Pole; with atlas | last=Gould | first=Benjamin Apthorp | journal=Resultados del Observatorio Nacional Argentino | volume=1 | page=140 | date=1878 | bibcode=1879RNAO....1....1G }}</ref> An occasional name seen in English is ''Soheil'', or the feminine Soheila; in Turkish is ''Süheyl'', or the feminine Süheyla, from the Arabic name for several bright stars, سهيل ''suhayl'',<ref name="hinkley63"/> and Canopus was known as Suhel {{IPAc-en|'|s|uː|h|E|l}} in medieval times.<ref name=kunitzsch/> Alternative spellings include Suhail, Souhail, Suhilon, Suheyl, Sohayl, Suhayil, Shoel, Sohil, Soheil, Sahil, Suhayeel, Sohayil, Sihel, and Sihil.<ref name="hinkley63"/> An alternative name was ''Wazn'' "weight" or ''Haḍar'' "ground", possibly related to its low position near the horizon.<ref name="hinkley63"/> Hence comes its name in the ''[[Alfonsine tables]]'', Suhel ponderosus, a Latinization of ''Al Suhayl al Wazn''.<ref name="hinkley63"/> Its Greek name was revived during the [[Renaissance]].<ref name=kunitzsch>{{cite book |last1=Kunitzsch|first1=Paul |last2=Smart|first2=Tim |date = 2006|title = A Dictionary of Modern star Names: A Short Guide to 254 Star Names and Their Derivations |edition = 2nd rev. |publisher = Sky Publishing Corporation |location = Cambridge, Massachusetts |isbn = 978-1-931559-44-7 |page = 23}}</ref> ==Observation== [[File:Carina constellation map.svg|thumb|left|The constellation [[Carina (constellation)|Carina]] with Canopus towards the right (west)]] The Spanish Muslim astronomer [[Ibn Rushd]] went to [[Marrakesh]] (in Morocco) to observe the star in 1153, as it was invisible in his native [[Córdoba, Spain|Córdoba]], [[Al-Andalus]]. He used the different visibility in different latitudes to argue that the [[Spherical Earth|earth is round]], following [[Spherical Earth#Aristotle|Aristotle's argument]] which held that such an observation was only possible if the earth was a relatively small sphere.<ref name=ibn_rushd>{{cite encyclopedia|first1=Juan|last1=Vernet|author-link1=Juan Vernet|first2=Julio|last2=Samsó|author-link2=Julio Samsó |title=The development of Arabic science in Andalusia |page=264|editor=[[Roshdi Rashed]]|encyclopedia=Encyclopedia of the History of Arabic Science | date=1996|publisher=Routledge|isbn=978-0-415-12410-2|oclc=912501823}}</ref> English explorer [[Robert Hues]] brought Canopus to the attention of European observers in his 1592 work ''Tractatus de Globis'', along with [[Achernar]] and [[Alpha Centauri]], noting:<blockquote>"Now, therefore, there are but three [[First-magnitude star|Stars of the first magnitude]] that I could perceive in all those parts which are never seene here in England. The first of these is that bright Star in the sterne of [[Argo Navis|Argo]] which they call Canobus. The second is in the end of [[Eridanus (constellation)|Eridanus]]. The third is in the right foote of the [[Centaurus|Centaure]]."<ref>Knobel, p. 416.</ref></blockquote> [[File:Vela and Surrounding Constellations (ground-based image).jpg|right|thumb|Wide angle view showing Canopus and other prominent stars with the Milky Way|alt=A field of stars against the Milky Way background with the prominent stars and constellations labelled]] In the [[Southern Hemisphere]], Canopus and [[Sirius]] are both visible high in the sky simultaneously, and reach a [[meridian (astronomy)|meridian]] just {{val|21|u=minutes}} apart. Brighter than [[first-magnitude star|first magnitude]], Canopus can be seen by naked eye in the early twilight. Mostly visible in mid to late summer in the Southern Hemisphere, Canopus [[Culmination|culminates]] at midnight on December 27,<ref name="motz" /> and at 9 PM on February 11.<ref name="Schaaf257">Schaaf, p. 257.</ref> When seen from latitudes south of {{DEC|37|18}}&nbsp;S, Canopus is a [[circumpolar star]]. Since Canopus is so far south in the sky, it never rises in mid- to far-northern latitudes; in theory the northern limit of visibility is latitude {{DEC|37|18}} north. This is just south of [[Athens]], [[Richmond, Virginia]] (USA), and [[San Francisco]], and very close to [[Seville]] and [[Agrigento]]. It is almost exactly the latitude of [[Lick Observatory]] on [[Mount Hamilton (California)|Mt. Hamilton, California]], from which it is readily visible because of the effects of elevation and [[atmospheric refraction]], which add another degree to its apparent altitude. Under ideal conditions, it can be spotted as far north as latitude {{DEC|37|31}} from the Pacific coast.<ref>D. Gieringer, "Exploring the Tropic of Canopus", ''Astronomy'', December 1985, p.24.</ref> Another northernmost record of visibility came from [[Mount Nemrut]] in Turkey, latitude {{DEC|37|59}}.<ref>{{cite web |last1=Tezel |first1=Tunç |author-link=Tunç Tezel |url=http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |title=Zodiacal Light and Nemrut Heritage |work=The World At Night (TWAN) |access-date=17 March 2014 |date=8 Oct 2013 |archive-url=https://web.archive.org/web/20140317134955/http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |archive-date=17 March 2014 |url-status=dead }}</ref> It is more easily visible in places such as the Gulf Coast and Florida, and the island of [[Crete]] (Greece) where the best season for viewing it around 9 p.m. is during late January and early February.<ref name="motz">{{cite book|last1=Motz|first1=Lloyd|last2=Nathanson|first2=Carol|title=The Constellations: An Enthusiast's Guide to the Night Sky|publisher=Aurum Press|location=London, United Kingdom|date=1991|pages=376–77|isbn=1-85410-088-2}}</ref> Canopus has a B–V [[color index]] of +0.15—where 0 is a blue-white—indicating it is essentially white, although it has been described as yellow-white. Canopus' spectral type has been given as F0 and the incrementally warmer A9. It is less yellow than [[Altair]] or [[Procyon]], with indices measured as 0.22 and 0.42, respectively.<ref name=Hoffleit1991>{{cite book | title=Bright Star Catalogue | edition=5th Revised | last1=Hoffleit | first1=D. | last2=Warren Jr. | first2=W. H. | date=1991 | publisher=[[Centre de Données astronomiques de Strasbourg|CDS]] }}</ref> Some observers may have perceived Canopus as yellow-tinged because it is low in the sky and hence subject to atmospheric effects.<ref name="Schaaf112">Schaaf, pp. 112–13.</ref> [[Patrick Moore]] said that it never appeared anything but white to him.<ref name="moore2000">{{cite book | first1=Patrick | last1=Moore | title=Exploring the night sky with binoculars | edition=4th | publisher=Cambridge University Press | year=2000 | isbn=9780521793902 | page=[https://archive.org/details/exploringnightsk00moor/page/69 69] | url=https://archive.org/details/exploringnightsk00moor| url-access=registration }}</ref> The [[bolometric correction]] for Canopus is 0.00,<ref name=smiljanic2006/> indicating that the visual [[absolute magnitude]] and bolometric absolute magnitude are equal. Canopus was previously proposed to be a member of the [[Scorpius–Centaurus association]], however it is not located near the subgroups of that association, and has not been included as a Sco-Cen member in kinematic studies that used [[Hipparcos]] astrometric data.<ref name="deZeeuw">{{cite journal|last1=de Zeeuw|first1=P.T. |last2=Hoogerwerf|first2=R. |last3=de Bruijne|first3=J.H.J |last4=Brown|first4=A.G.A |last5=Blaauw|first5=A. |date=1999|title=A HIPPARCOS Census of the Nearby OB Associations |journal=The Astronomical Journal |volume=117 |issue=1 |pages=354–399|bibcode=1999AJ....117..354D |doi=10.1086/300682|arxiv = astro-ph/9809227 |s2cid=16098861 }}</ref> Canopus is not thought to be a member of any nearby young stellar groups.<ref name=mamajek>{{cite journal | url=https://figshare.com/articles/Canopus_B_A_Candidate_Common_Proper_Motion_Companion_to_the_Second_Brightest_Star/1132696 | title=Canopus B: A Candidate Common Proper Motion Companion to the Second Brightest Star | last=Mamajek | first=Eric | year=2014 | publisher=Figshare | doi=10.6084/m9.figshare.1132696.v3 | access-date=2020-09-10 }}</ref> In 2014, astronomer Eric Mamajek reported that an extremely magnetically active M dwarf (having strong coronal X-ray emission), 1.16 degrees south of Canopus, appears to share a [[common proper motion]] with Canopus. The projected separation of the M dwarf 2MASS J06234738-5351131 ("Canopus B") is approximately 1.9 parsecs. However, despite this large separation, it is still within the estimated tidal radius (2.9 parsecs) for the massive star Canopus.<ref name="mamajek"/> No star closer than Canopus is more luminous than it, and it has been the brightest star in Earth's night sky during three epochs over the past four million years. Other stars appear brighter only during relatively temporary periods, during which they are passing the Solar System much closer than Canopus. About 90,000 years ago, [[Sirius]] moved close enough that it became brighter than Canopus, and that will remain so for another 210,000 years. But in 480,000 years, as Sirius moves further away and appears fainter, Canopus will once again be the brightest, and will remain so for a period of about 510,000 years.<ref name="tomkin98">{{cite journal|last=Tomkin|first=Jocelyn|date=April 1998|title=Once and Future Celestial Kings|journal=Sky and Telescope|volume=95|issue=4|pages=59–63|bibcode=1998S&T....95d..59T}}</ref><!-- this all comes from same paper --> ===Role in navigation=== The southeastern wall of the [[Kaaba]] in [[Mecca]] is aligned with the rising point of Canopus, and is also named ''Janūb''.<ref>{{cite book|author=George Nicholas Atiyeh|title=The Book in the Islamic World: The Written Word and Communication in the Middle East|url=https://books.google.com/books?id=t4LEfpCW_kQC|date=1 January 1995|publisher=SUNY Press|isbn=978-0-7914-2473-5}}</ref> The [[Negev Bedouin|Bedouin]] people of the [[Negev]] and [[Sinai Peninsula|Sinai]] knew Canopus as ''Suhayl'', and used it and [[Polaris]] as the two principal stars for navigation at night. Because it disappears below the horizon in those regions, it became associated with a changeable nature, as opposed to always-visible Polaris, which was circumpolar and hence 'steadfast'.<ref>{{cite journal |last=Bailey |first=Clinton |date=1974 |title=Bedouin Star-Lore in Sinai and the Negev |journal=Bulletin of the School of Oriental and African Studies, University of London |volume=37 |issue=3 |pages=580–96 |type=abstract |doi=10.1017/S0041977X00127491 |jstor=613801|s2cid=131527348 }}</ref> The south [[celestial pole]] can be approximately located using Canopus and another bright star, [[Achernar]], as the three make an [[equilateral triangle]]. Canopus sits on an imaginary line that extends {{DEC|36}} one way to Sirius and {{DEC|37}} to the south celestial pole.<ref>{{Cite book| last1 = Heifetz| first1 = Milton| last2 = Tirion| first2 = Wil| title = A Walk Through the Heavens: A Guide to Stars and Constellations and Their Legends | date = 2007| publisher = [[Cambridge University Press]]| location = Cambridge | page = 38 | isbn=978-1-139-46138-2}}</ref> Canopus's brightness and location well off the [[ecliptic]] make it useful for space navigation. Many spacecraft carry a special camera known as a "Canopus [[star tracker|Star Tracker]]" plus a Sun sensor for [[Orientation (geometry)|attitude]] determination. [[Mariner 4]] used Canopus for [[Spin-stabilisation|second axis stabilisation]] (after locking on the Sun) in 1964, the first time a star had been used.<ref>{{cite book |last1=United States. National Aeronautics and Space Administration. Scientific and Technical Information Division |title=Astronautics and Aeronautics, 1964: Chronology on Science, Technology and Policy |date=1965 |publisher=Scientific and Technical Information Division, National Aeronautics and Space Administration |page=398 |url=https://books.google.com/books?id=ckkCAAAAIAAJ&pg=PA398}}</ref> ==Spectrum== Canopus was little-studied by western scientists before the 20th century. It was given a spectral class of F in 1897, an early use of this extension to [[Secchi class]] I, applied to those stars where the hydrogen lines are relatively weak and the [[calcium K line]] relatively strong.<ref>{{cite journal |bibcode=1897ApJ.....6..349P |title=Spectra of bright southern stars |last1=Pickering |first1=E. C. |last2=Cannon |first2=A. J. |journal=The Astrophysical Journal |year=1897 |volume=6 |page=349 |doi=10.1086/140407 }}</ref> It was given as a standard star of F0 in the [[Henry Draper Catalogue]], with the spectral type F0 described as having hydrogen lines half the strength of an A0 star and the calcium K line three times as strong as Hδ.<ref name=hd>{{cite journal |bibcode=1918AnHar..92....1C |title=The Henry Draper catalogue : 4h, 5h and 6h |last1=Cannon |first1=Annie Jump |last2=Pickering |first2=Edward Charles |journal=Annals of Harvard College Observatory |year=1918 |volume=92 |page=1 }}</ref> American astronomer [[Jesse L. Greenstein|Jesse Greenstein]] was interested in stellar spectra and used the newly built [[Otto Struve Telescope]] at [[McDonald Observatory]] to analyze the star's spectrum in detail.<ref>{{cite book |last1=Trimble |first1=Virginia | first2= Thomas R. |last2=Williams | first3= Katherine | last3=Bracher| first4= Richard | last4=Jarrell| first5=Jordan D.| last5= Marché| first6=F. Jamil | last6=Ragep |title=Biographical Encyclopedia of Astronomers |date=2007 |publisher=Springer Science & Business Media |location=New York, New York |isbn=978-0-387-30400-7 |page=438 |url=https://books.google.com/books?id=t-BF1CHkc50C&pg=PA438}}</ref> In a 1942 paper, he reported that the spectrum is dominated by strong broad hydrogen lines. There are also [[absorption line]]s of carbon, nitrogen, oxygen, sulphur, iron, and many ionised metals.<ref name=greenstein1942>{{cite journal |bibcode=1942ApJ....95..161G |title=The Spectrum of α Carinae |last1=Greenstein |first1=Jesse L. |journal=The Astrophysical Journal |year=1942 |volume=95 |page=161 |doi=10.1086/144382 }}</ref> It was studied in the [[ultraviolet]] by an early astronomical satellite, [[Gemini XI]] in 1966. The UV spectra were considered to be consistent with an F0 [[Supergiant star|supergiant]] having a temperature of {{val|6,900|fmt=commas|u=K}}, the accepted parameters for Canopus at the time.<ref name=kondo1970>{{cite journal |bibcode=1970ApJ...159..927K |title=Ultraviolet Spectrophotometry of Canopus from Gemini XI |last1=Kondo |first1=Y. |last2=Henize |first2=K. G. |last3=Kotila |first3=C. L. |journal=The Astrophysical Journal |year=1970 |volume=159 |page=927 |doi=10.1086/150370 }}</ref> New Zealand-based astronomers [[John Hearnshaw]] and Krishna Desikachary examined the spectrum in greater detail, publishing their results in 1982.<ref>{{cite journal |title=The spectrum of Canopus | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 198 | year= 1982 | issue= 2 | pages= 311–320 | doi= 10.1093/mnras/198.2.311 | bibcode=1982MNRAS.198..311H| doi-access= free }}</ref><ref>{{cite journal |title=The spectrum of Canopus II - Analysis and composition | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 201 | year= 1982 | issue= 3 | pages= 707–721 | doi= 10.1093/mnras/201.3.707 | bibcode=1982MNRAS.201..707D| doi-access= free }}</ref> When [[luminosity class]]es were added to the MK spectral classification scheme, Canopus was assigned class Iab indicating an intermediate luminosity supergiant. This was based on the relative strengths of certain spectral lines understood to be sensitive to the luminosity of a star.<ref name=devaucoleurs>{{cite journal|title=Spectral types and luminosities of B, A and F southern stars|author=de Vaucouleurs, A.|journal=Monthly Notices of the Royal Astronomical Society|volume=117|page=449|date=1957|issue=4|bibcode=1957MNRAS.117..449D|doi=10.1093/mnras/117.4.449|doi-access=free}}</ref> In the [[Bright Star Catalogue]] 5th edition it is given the spectral class F0II, the luminosity class indicating a [[bright giant]].<ref name=bsc>{{cite book |bibcode=1991bsc..book.....H |year=1991 |title=The Bright star catalogue |last1=Hoffleit |first1=Dorrit |last2=Jaschek |first2=Carlos }}</ref> [[Balmer line]] profiles and oxygen line strengths indicate the size and luminosity of Canopus.<ref name=kovtyukh2012>{{cite journal |bibcode=2012MNRAS.423.3268K |title=Accurate luminosities from the oxygen λ7771-4 Å triplet and the fundamental parameters of F-G supergiants |last1=Kovtyukh |first1=V. V. |last2=Gorlova |first2=N. I. |last3=Belik |first3=S. I. |journal=Monthly Notices of the Royal Astronomical Society |year=2012 |volume=423 |issue=4 |page=3268 |doi=10.1111/j.1365-2966.2012.21117.x |arxiv=1204.4115 |s2cid=118683158 }}</ref> When the effects of stellar rotation speed on spectral lines are accounted for, the MK spectral class of Canopus is adjusted to A9II.<ref name=perkins/> Its spectrum consists mostly of absorption lines on a visible [[continuous spectrum|continuum]], but some emission has been detected. For example, the [[calcium K line]] have weak emission wings on each side of the strong central absorption line, first observed in 1966. The emission line profiles are usually correlated with the luminosity of the star as described by the [[Wilson-Bappu effect]], but in the case of Canopus they indicate a luminosity much lower than that calculated by other methods.<ref name=warner1966>{{cite journal|title=CA II emission in the spectrum of Canopus|journal=The Observatory |volume=86 |pages=82|date=April 1966|last=Warner |first=B. |bibcode=1966Obs....86...82W }}</ref> More detailed observations have shown that the emission line profiles are variable and may be due to [[plage (astronomy)|plage]] areas on the surface of the star. Emission can also be found in other lines such as the h and k lines of ionised magnesium.<ref name=bappu1984>{{cite journal |bibcode=1984BASI...12..196B |title=CA II K emission in Canopus |last1=Bappu |first1=M. K. V. |last2=Mekkaden |first2=M. V. |last3=Rao |first3=N. K. |journal=Bulletin of the Astronomical Society of India |year=1984 |volume=12 |page=196 }}</ref> ==Distance== Before the launch of the [[Hipparcos]] satellite telescope, distance estimates for Canopus varied widely, from 96 [[light-year]]s to 1200 light-years. The closer distance was derived from parallax measurements of around {{val|33|ul=mas}}.<ref name=vandekamp1943>{{cite journal |title=Note on the Parallax of Canopus|journal=Popular Astronomy |volume=51 |date=1943 |page=172 |last=van de Kamp |first=Peter|bibcode=1943PA.....51..172V }}</ref> The larger distance derives from the assumption of a very bright [[absolute magnitude]] for Canopus.<ref name=vanzyl>{{cite book|author=J.E. van Zyl|title=Unveiling the Universe: An Introduction to Astronomy|url=https://books.google.com/books?id=Cj7uBwAAQBAJ&pg=PA184|date=6 December 2012|publisher=Springer Science & Business Media|isbn=978-1-4471-1037-8|pages=184–}}</ref> Hipparcos established Canopus as being {{val|310|u=light-years}} ({{val|95|ul=parsecs}}) from the [[Solar System]]; this is based on its 2007 [[parallax]] measurement of {{Val|10.43|0.53|ul=mas}}.<ref name="van Leeuwen2007"/> At 95 parsecs, the [[interstellar extinction]] for Canopus is low at 0.26 magnitudes.<ref name=DomicianoDeSouza/> Canopus is too bright to be included in the normal observation runs of the [[Gaia satellite]] and there is no published Gaia parallax for it.<ref name=dr2>{{cite DR2}}</ref> At present the star is drifting further away from the Sun with a [[radial velocity]] of 20&nbsp;km/s. Some 3.1&nbsp;million years ago it made the closest approach to the Sun at a distance of about {{convert|52.87|pc|ly|0|adj=ri0|order=flip|abbr=on|lk=off}}. Canopus is orbiting the Milky Way with a heliocentric velocity of 24.5&nbsp;km/s and a low [[orbital eccentricity|eccentricity]] of 0.065.<ref name=Anderson2012>{{citation | last1=Anderson | first1=E. | last2=Francis | first2=Ch. | title=XHIP: An extended hipparcos compilation | journal=Astronomy Letters | volume=38 | issue=5 | pages=331 | year=2012 | bibcode=2012AstL...38..331A | arxiv=1108.4971 | doi=10.1134/S1063773712050015 | s2cid=119257644 | postscript=. }}</ref> ==Physical characteristics== [[File:Constellation_Carina.jpg|thumb|right|upright|Canopus is the brightest star in the constellation of Carina (top).]] The [[absorption line]]s in the spectrum of Canopus shift slightly with a period of {{val|6.9|u=days}}. This was first detected in 1906 and the [[doppler effect|Doppler]] variations were interpreted as orbital motion.<ref name=curtis1907>{{cite journal |bibcode=1907PASP...19R.259C |title=The orbits of the spectroscopic binaries alpha Carinae, kappa Velorum, and alpha Pavonis |last1=Curtis |first1=H. D. |journal=Publications of the Astronomical Society of the Pacific |year=1907 |volume=19 |page=259 |doi=10.1086/121781 }}</ref> An orbit was even calculated, but no such companion exists and the small radial velocity changes are due to movements in the atmosphere of the star. The maximum observed [[radial velocities]] are only 0.7 to {{val|1.6|ul=km/s}}. Canopus also has a magnetic field that varies with the same period, detected by the [[Zeeman splitting]] of its spectral lines.<ref name=weiss1986>{{cite journal |bibcode=1986A&A...160..243W | title=The magnetic field of Canopus | last=Weiss | first=W. W. | journal= Astronomy and Astrophysics |volume= 160|pages= 243–250 | year=1986}}</ref> Canopus is bright at [[microwave]] wavelengths, one of the few F-class stars to be detected by radio.<ref name=gudel2002>{{cite journal |bibcode=2002ARA&A..40..217G |title=Stellar Radio Astronomy: Probing Stellar Atmospheres from Protostars to Giants |last1=Güdel |first1=Manuel |journal=Annual Review of Astronomy and Astrophysics |year=2002 |volume=40 |pages=217–261 |doi=10.1146/annurev.astro.40.060401.093806 |arxiv=astro-ph/0206436 |s2cid=53633983 }}</ref> The [[rotation period]] of the star is not accurately known, but may be over three hundred days.<ref name=Testa2004>{{cite journal | title=The Density of Coronal Plasma in Active Stellar Coronae | last1=Testa | first1=Paola | last2=Drake | first2=Jeremy J. | last3=Peres | first3=Giovanni | journal=The Astrophysical Journal | volume=617 | issue=1 | pages=508–530 | date=December 2004 | doi=10.1086/422355 | arxiv=astro-ph/0405019 | bibcode=2004ApJ...617..508T | s2cid=17532089 }}</ref> The [[projected rotational velocity]] has been measured at 9&nbsp;km/s.<ref name=ayres2018/> An early [[Interferometry|interferometric]] measurement of its [[angular diameter]] in 1968 gave a [[Limb darkening|limb-darkened]] value of {{val|6.86|ul=mas}}, close to the accepted modern value.<ref>{{cite journal |bibcode=1968ARA&A...6...13B |title=Measurement of Stellar Diameters |last1=Brown |first1=R. Hanbury |journal=Annual Review of Astronomy and Astrophysics |year=1968 |volume=6 |page=13 |doi=10.1146/annurev.aa.06.090168.000305 }}</ref> [[Very-long-baseline interferometry]] has been used to calculate Canopus' angular diameter at {{val|6.9|ul=mas}}. Combined with distance calculated from its Hipparcos parallax, this gives it a radius of 71 times [[Solar radius|that of the Sun]].<ref name=vlti/> If it were at the centre of the Solar System, it would extend 90% of the way to the orbit of [[Mercury (planet)|Mercury]].<ref name=Kalerstars>{{cite web|url=http://stars.astro.illinois.edu/sow/canopus.html|title=Canopus|last=Kaler|first=Jim|work=Stars|publisher=University of Illinois|access-date=8 July 2012|date=26 June 2009}}</ref> The radius and temperature relative to the Sun means that it is 10,700 times more luminous than the Sun, and its position in the [[H-R diagram]] relative to theoretical [[stellar evolution|evolutionary]] tracks means that it is {{Val|8.0|0.3}} times as massive as the Sun.<ref name=vlti/> Measurements of its shape find a 1.1° departure from spherical symmetry.<ref name=cruzalebes2015>{{cite journal |bibcode=2015MNRAS.446.3277C |title=Departure from centrosymmetry of red giants and supergiants measured with VLTI/AMBER |last1=Cruzalèbes |first1=P. |last2=Jorissen |first2=A. |last3=Chiavassa |first3=A. |last4=Paladini |first4=C. |last5=Rabbia |first5=Y. |last6=Spang |first6=A. |journal=Monthly Notices of the Royal Astronomical Society |year=2015 |volume=446 |issue=4 |page=3277 |doi=10.1093/mnras/stu2382 |doi-access=free }}</ref> Canopus is a source of [[X-ray astronomy|X-rays]], which are probably produced by its corona, magnetically heated to several million [[Kelvin]]. The temperature has likely been stimulated by fast rotation combined with strong convection percolating through the star's outer layers.<ref name=ness>{{cite journal|bibcode=2004A&A...427..667N|title=On the sizes of stellar X-ray coronae|journal=Astronomy and Astrophysics|volume=427|issue=2|pages=667–683|last1=Ness|first1=J.-U.|last2=Güdel|first2=M.|last3=Schmitt|first3=J. H. M. M.|last4=Audard|first4=M.|last5=Telleschi|first5=A.|year=2004|doi=10.1051/0004-6361:20040504|arxiv = astro-ph/0407231 |s2cid=11468731}}</ref> The soft X-ray sub-coronal X-ray emission is much weaker than the hard X-ray coronal emission. The same behaviour has been measured in other F-class supergiants such as [[α Persei]] and is now believed to be a normal property of such stars.<ref name=ayres2018/> == Evolution == The spectrum of Canopus indicates that it has exhausted its core hydrogen and [[stellar evolution|evolved]] away from the [[main sequence]], where it spent some 30 million years of its existence as a blue-white star <!-- source suggests B2V but may be too exact --> of around 10 solar masses.<ref>{{cite journal |last1=Peimbert |first1=M. |last2=Wallerstein | first2= G.| last3= Pilachowski | first3= C. A. |title=An upper limit for the deuterium abundance in Canopus |journal=Astronomy and Astrophysics |date=1981 |volume=104 |issue=1 |pages=72–74 | bibcode=1981A&A...104...72P}}</ref> The position of Canopus in the [[H–R diagram]] indicates that it is currently in the core-helium burning phase.<ref name=vlti/> It is an intermediate mass star that has left the [[red-giant branch]] before its core became [[degenerate matter|degenerate]] and is now in a [[blue loop]].<ref name=desouza>{{Cite journal | last1 = Domiciano De Souza | first1 = A. | last2 = Bendjoya | first2 = P. | last3 = Vakili | first3 = F. | last4 = Millour | first4 = F. | last5 = Petrov | first5 = R. G. | title = Diameter and photospheric structures of Canopus from AMBER/VLTI interferometry | doi = 10.1051/0004-6361:200810450 | journal = Astronomy and Astrophysics | volume = 489 | issue = 2 | pages = L5–L8 | year = 2008 |bibcode = 2008A&A...489L...5D | url = https://hal.archives-ouvertes.fr/hal-00316994/document | doi-access = free }}</ref> Models of stellar evolution in the blue loop phase show that the length of the blue loop is strongly affected by rotation and mixing effects inside the star. It is difficult to determine whether a star is currently evolving towards hotter temperature or returning to cooler temperatures, since the evolutionary tracks for stars with different masses overlap during the blue loops.<ref name=smiljanic2006>{{cite journal |bibcode=2006A&A...449..655S |title=CNO in evolved intermediate mass stars |last1=Smiljanic |first1=R. |last2=Barbuy |first2=B. |last3=De Medeiros |first3=J. R. |last4=Maeder |first4=A. |journal=Astronomy and Astrophysics |year=2006 |volume=449 |issue=2 |page=655 |doi=10.1051/0004-6361:20054377 |arxiv=astro-ph/0511329 |s2cid=3711409 }}</ref> Canopus lies on the warm side of the [[instability strip]] and does not pulsate like [[Cepheid variables]] of a similar luminosity.<ref name=ayres2011>{{cite journal |doi=10.1088/0004-637X/738/2/120 |title=The Curious Case of the Alpha Persei Corona: A Dwarf in Supergiant's Clothing? |year=2011 |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |volume=738 |issue=2 |page=120 |bibcode=2011ApJ...738..120A |doi-access=free }}</ref> However its atmosphere does appear to be unstable, showing strong signs of convection.<ref name=smiljanic2006/> Canopus may not be massive enough for its [[nuclear fusion|fusion]] chain to reach iron and trigger a core collapse and subsequent [[supernova]], instead eventually becoming a neon-oxygen [[white dwarf]].<ref name=Kalerstars/> ==Cultural significance == Canopus was known to the ancient Mesopotamians and given the name ''NUN-ki'' and represented the city of [[Eridu]] in the ''Three Stars Each'' [[Babylonian star catalogues]] and later [[MUL.APIN]] around 1100 BC.<ref>{{cite journal | last = Rogers | first = John H. | date = 1998 | title = Origins of the Ancient Constellations: I. The Mesopotamian Traditions | journal = Journal of the British Astronomical Association | volume = 108 | issue = 1 | pages = 9–28 | bibcode = 1998JBAA..108....9R}}</ref> Today, the star [[Sigma Sagittarii]] is known by the common name Nunki.<ref name=allen>{{citation | page=359 | first1=Richard Hinckley | last1=Allen | title=Star Names, their lore and meaning}}</ref> Canopus was not visible to the mainland [[Ancient Greece|ancient Greeks]] and [[Roman Empire|Romans]]; it was, however, visible to the [[ancient Egypt]]ians.<ref name="Schaaf107">Schaaf, p. 107.</ref> Hence [[Aratus]] did not write of the star as it remained below the horizon, while [[Eratosthenes]] and [[Ptolemy]]—observing from [[Alexandria]]—did, calling it ''Kanōbos''.<ref name=ridpathCr>{{cite web| url=http://www.ianridpath.com/startales/carina.htm | title=Carina |last1=Ridpath|first1=Ian|publisher=self-published |work=Star Tales | access-date= 10 December 2015}}</ref> An [[Egypt]]ian priestly poet in the time of [[Thutmose III]] mentions the star as ''Karbana,'' "the star which pours his light in a glance of fire, when he disperses the morning dew."<ref name="hinkley63" /> Under the [[Ptolemies]], the star was known as ''Ptolemaion'' ([[Ancient Greek|Greek]]: Πτολεμαῖον) and its [[acronychal rising]] marked the date of the Ptolemaia festival, which was held every four years, from 262 to 145 BC.<ref>[[Martianus Capella]] 7.838, {{cite journal | last1 = Hazzard | last2 = Fitzgerald | year = 1991 | title = The Regulation of the Ptolemeia | journal = Journal of the Royal Astronomical Society of Canada | volume = 85 | pages = 6–23 |bibcode = 1991JRASC..85....6H }}; Hazzard. 2000. ''Imagination of a Monarchy: Studies in Ptolemaic Propaganda'', 34–36.</ref> [[File:Statue of Averroes in Córdoba, Spain.jpg|thumb|upright|[[Averroes]], who used his 1153 observation of Canopus in [[Marrakesh]] while the star was invisible in his native Spain as an argument that the [[Spherical Earth|earth is round]].<ref name=ibn_rushd/>]] ===India=== In Indian [[Vedas|Vedic literature]], Canopus is associated with the sage [[Agastya]], one of the ancient [[siddhar]]s and [[rishi]]s (the others are associated with the stars of the [[Big Dipper]]).<ref name="Frawley 1993">{{cite book|last=Frawley|first=David|title=Gods, Sages and Kings: Vedic Secrets of Ancient Civilization|publisher=Motilal Banarsidass |location=New Delhi, India|date=1993}}</ref> To Agastya, the star is said to be the 'cleanser of waters', and its rising coincides with the calming of the waters of the [[Indian Ocean]]. It is thus considered the son of [[Pulastya]], son of [[Brahma]]. Canopus is described by [[Pliny the Elder]] and [[Gaius Julius Solinus]] as the largest, brightest and only source of [[starlight]] for navigators near [[Tamraparni]] island (ancient Sri Lanka) during many nights.<ref>{{cite book |last1=Pridham |first1=Charles |title=An Historical, Political, and Statistical Account of Ceylon and Its Dependencies |date=1849 |publisher=T. and W. Boone |page=7 |url=https://books.google.com/books?id=O4aqHOMSJdYC&pg=PR19-IA5|language=en}}</ref><ref name="Frawley 1993"/><ref>{{cite book |last1=Elder |first1=Pliny the |title=Delphi Complete Works of Pliny the Elder (Illustrated) |date=2015 |publisher=Delphi Classics |url=https://books.google.com/books?id=OrJ0CgAAQBAJ&pg=PA343|language=en}}</ref> ===China=== Canopus was described as Shou Xing, the Star of Longevity, in the ''Shiji'' ([[Records of the Grand Historian]]) completed in 94 BC by Chinese historian [[Sima Qian]].<ref name=fong83>{{cite journal | title=The Iconography of the Popular Gods of Happiness, Emolument, and Longevity (Fu Lu Shou) | first=Mary H. |last=Fong | journal=Artibus Asiae | volume= 44 | issue= 2/3 | year=1983| pages= 159–199 | doi= 10.2307/3249596| jstor=3249596 }}</ref> Drawing on sources from the [[Warring States period]], he noted it to be the southern counterpart of [[Sirius]],<ref name="IDP"/> and wrote of a sanctuary dedicated to it established by Emperor [[Qin Shi Huang]] between 221 and 210 BC. During the [[Han dynasty]], the star was auspicious, its appearance in the southern sky heralding peace and absence war.<ref name=fong83/> From the imperial capital [[Chang'an]], the star made a low transit across the southern sky, indicating true south to observers, and was often obscured by clouds.<ref name=baumann19>{{cite journal | title=The White Old Man: Géluk-Mongolian Canopus Allegory and the Existence of God | first=Brian | last=Baumann | journal= Central Asiatic Journal | volume= 62 | issue= 1 | year=2019| pages= 35–68 | doi=10.13173/centasiaj.62.1.0035| s2cid=213083544 }}</ref> During this time it was also equated with [[Old Man of the South Pole]] (in {{zh|c=南极老人|p=Nanji Lǎorén}})<ref name=fong83/> Under this name, Canopus appears (albeit misplaced northwards) on the medieval Chinese manuscript the [[Dunhuang Star Chart]], although it cannot be seen from the Chinese capital of [[Chang'an]].<ref name="IDP">{{cite journal|bibcode=2009JAHH...12...39B|arxiv=0906.3034|title=The Dunhuang Sky: A Comprehensive Study of the Oldest Known Star Atlas|volume=12|issue=1|pages=39–59|last1=Bonnet-Bidaud|first1=Jean-Marc |last2=Praderie|first2=Françoise |last3=Whitfield|first3=Susan |author-link=Susan Whitfield |journal=The International Dunhuang Project: The Silk Road Online|year=2009}}</ref> The Chinese astronomer [[Yi Xing]] had journeyed south to chart Canopus and other far southern stars in 724 AD.<ref>{{cite book|last=Needham|first=Joseph|title=Science and Civilisation in China: Volume 3, Mathematics and the Sciences of the Heavens and the Earth|publisher=Cambridge University Press|location=Cambridge, United Kingdom|date=1959|pages=274|isbn=0521058015}}</ref> Its personification as the Old Man Star was popularised in the [[Tang Dynasty]], where it appeared often in poetry and memorials. Later still, during the [[Ming Dynasty]], the star was established as one of the [[Sanxing (deities)|Three Stars]] (Fu Lo Shou), appearing frequently in art and literature of the time.<ref name=fong83/> This symbolism spread into neighbouring cultures in Asia.<ref name=baumann19/> In Japan, Canopus is known as ''Mera-boshi'' and ''Roujin-sei'' (the old man star),<ref>{{cite conference |url=http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |title=Stellar Iconology and Astronomical Folklore in Japan |author=Takao Ibaraki |book-title=International Planetarium Society (IPS) Conferences 1996 |publisher=International Planetarium Society |location=Osaka |date=14 July 1996 |access-date=25 February 2012 |url-status=dead |archive-url=https://web.archive.org/web/20120326195757/http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |archive-date=2012-03-26 }}</ref> and in Mongolia, it was personified as the White Old Man.<ref name=fong83/> Although the link was known in Tibet, with names such as ''Genpo karpo'' (''Rgan po dkar po'') or ''Genkar'' (''Rgan dkar'') "White Old Man", the symbolism was not popular. Instead, Canopus was more commonly named ''Karma Rishi སྐར་མ་རི་ཥི།'', derived from Indian mythology. Tibetans celebrated the star's heliacal rising with ritual bathing and associated it with morning dew.<ref name=baumann19/> ===Polynesia=== Bright stars were important to the ancient [[Polynesian culture|Polynesians]] for navigation between the many islands and atolls of the Pacific Ocean. Low on the horizon, they acted as stellar compasses to assist mariners in charting courses to particular destinations. Canopus served as the southern wingtip of a "Great Bird" constellation called ''Manu'', with Sirius as the body and [[Procyon]] the northern wingtip, which divided the Polynesian night sky into two hemispheres.<ref name="Holberg">{{cite book | last=Holberg | first=J.B. | title=Sirius: Brightest Diamond in the Night Sky | date=2007 | publisher=Praxis Publishing | location=Chichester, UK | isbn=978-0-387-48941-4 | pages=[https://archive.org/details/siriusbrightestd0000holb/page/25 25–26] | url=https://archive.org/details/siriusbrightestd0000holb/page/25 }}</ref> The [[Hawaiian people]] called Canopus ''Ke Alii-o-kona-i-ka-lewa'', "The chief of the southern expanse"; it was one of the stars used by [[Hawaiʻiloa]] and Ki when they traveled to the [[Southern Ocean]].{{sfn|Makemson|1941|p=198}} The [[Māori people]] of [[New Zealand|New Zealand/Aotearoa]] had several names for Canopus. ''[[Ariki]]'' ("High-born"), was known as a solitary star that appeared in the east, prompting people to weep and chant.{{sfn|Makemson|1941|p=201}} They also named it ''[[Atutahi]]'', ''Aotahi'' or ''Atuatahi'', "Stand Alone".<ref>p. 419, [https://books.google.com/books?id=p7dR2w1Wv2sC ''Mythology: Myths, Legends and Fantasies''], Janet Parker, Alice Mills, Julie Stanton, Durban, Struik Publishers, 2007.</ref> Its solitary nature indicates it is a ''[[Tapu (Polynesian culture)|tapu]]'' star, as ''tapu'' people are often solitary. Its appearance at the beginning of the ''Maruaroa'' season foretells the coming winter; light rays to the south indicate a cold wet winter, and to the north foretell a mild winter. Food was offered to the star on its appearance.<ref name="Best22">{{cite book|last=Best|first=Elsdon|title=Astronomical Knowledge of the Maori: Genuine and Empirical|publisher=Dominion Museum|location=Wellington, New Zealand|date=1922|pages=34–35|url=http://nzetc.victoria.ac.nz/tm/scholarly/tei-BesAstro-t1-body-d1-d6-d4.html}}</ref> This name has several mythologies attached to it. One story tells of how Atutahi was left outside the basket representing the [[Milky Way]] when [[Tāne]] wove it. Another related myth about the star says that Atutahi was the first-born child of [[Rangi and Papa|Rangi]], who refused to enter the Milky Way and so turned it sideways and rose before it. The same name is used for other stars and constellations throughout Polynesia.{{sfn|Makemson|1941|pp=200–202}} ''Kapae-poto'', "Short horizon", referred to it rarely setting as seen in New Zealand;{{sfn|Makemson|1941|p=217}} ''Kauanga'' ("Solitary") was the name for Canopus only when it was the last star visible before sunrise.{{sfn|Makemson|1941|p=218}} The people of the [[Society Islands]] had two names for Canopus, as did the [[Tuamotu]] people. The Society Islanders called Canopus ''Taurua-e-tupu-tai-nanu'', "Festivity-whence-comes-the-flux-of-the-sea", and ''Taurua-nui-o-te-hiti-apatoa'' "Great-festivity-of-the-border-of-the-south",{{sfn|Makemson|1941|p=259}} and the Tuamotu people called the star ''Te Tau-rari'' and ''Marere-te-tavahi'', the latter said to be the true name for the former, "He-who-stands-alone".{{sfn|Makemson|1941|p=229}} ===Africa=== In the [[Guanches|Guanche]] mythology of the island of [[Tenerife]] (Spain), the star Canopus was linked with the goddess [[Chaxiraxi]].<ref name="Rumeu">{{cite book|author=Antonio Rumeu de Armas|title=La conquista de Tenerife, 1494–1496|url=https://books.google.com/books?id=Ck4BAAAAMAAJ|year=1975|publisher=Aula de Cultura de Tenerife|isbn=9788450071078}}</ref> The [[Tswana people]] of [[Botswana]] knew Canopus as ''Naka''. Appearing late in winter skies, it heralded increasing winds and a time when trees lose their leaves. Stock owners knew it was time to put their sheep with rams.<ref>{{cite journal|last=Clegg|first=Andrew|date=1986|title=Some Aspects of Tswana Cosmology|journal=Botswana Notes and Records|volume=18|pages=33–37|jstor=40979758 }}</ref> In southern Africa, the Sotho, Tswana and Venda people called Canopus ''Naka'' or ''Nanga'', “the Horn Star”, while the Zulu and Swazi called it ''inKhwenkwezi'' "Brilliant star". It appears in the predawn sky in the third week of May. According to the Venda, the first person to see Canopus would blow a ''phalaphala'' horn from the top of a hill, getting a cow for a reward. The Sotho chiefs also awarded a cow, and ordered their medicine men to roll bone dice and read the fortune for the coming year.<ref name=snedegar95>{{cite journal |last1=Snedegar |first1=K.V. |title=Stars and seasons in Southern Africa |journal=Vistas in Astronomy |date=1995 |volume=39 |issue=4 |pages=529–38 |doi=10.1016/0083-6656(95)00008-9|bibcode=1995VA.....39..529S }}</ref> To the [[ǀXam language|ǀXam]]-speaking [[Bushmen]] of South Africa, Canopus and Sirius signalled the appearance of termites and flying ants. They also believed that stars had the power to cause death and misfortune, and they would pray to [[Sirius]] and Canopus in particular to impart good fortune or skill.<ref>{{cite journal| title="The Sky's Things", <nowiki>|</nowiki>xam Bushman 'Astrological Mythology' as recorded in the Bleek and Lloyd Manuscripts |last1=Hollman|first1=J. C.|journal=African Sky|volume= 11|page=8 |bibcode=2007AfrSk..11....8H|year = 2007 }}</ref> The [[ǃKung people]] of the [[Kalahari Desert]] in Botswana held Canopus and Capella to be the horns of ''tshxum'' (the Pleiades), the appearance of all three marking the end of the dry season and start of the rainy season.<ref>{{cite journal |last1=Marshall |first1=Lorna |title=Two Ju/ wa constellations |journal=Botswana Notes & Records |date=1975 |volume=7 |issue=1 |pages=153–159 | issn=0525-5090 |url=https://journals.co.za/docserver/fulltext/botnotes/7/1/548.pdf?expires=1590793041&id=id&accname=guest&checksum=3204085F9555AD9D083799E1F38E3AED}}</ref> ===Americas=== The [[Navajo]] observed the star and named it ''Maʼii Bizòʼ'', the “Coyote Star”. According to legend, Maʼii (Coyote) took part in the naming and placing of the star constellations during the creation of the universe. He placed Canopus directly south, naming it after himself.<ref name="Maryboy">Maryboy, Nancy D. (2004). ''A Guide to Navajo Astronomy.'' Indigenous Education Institute : Bluff, Utah.</ref> The [[Kalapalo]] people of [[Mato Grosso]] state in Brazil saw Canopus and [[Procyon]] as ''Kofongo'' "Duck", with [[Castor (star)|Castor]] and [[Pollux (star)|Pollux]] representing his hands. The asterism's appearance signified the coming of the rainy season and increase in [[manioc]], a food staple fed to guests at feasts.<ref name="basso87">{{cite book|last=Basso|first=Ellen B. |title=In Favor of Deceit: A Study of Tricksters in an Amazonian Society|publisher=University of Arizona Press|location=Tucson, Arizona|date=1987|page=[https://archive.org/details/infavorofdeceits0000bass/page/360 360]|isbn=0816510229|url=https://archive.org/details/infavorofdeceits0000bass|url-access=registration}}</ref> ===Australia=== Canopus is identified as the moiety ancestor ''Waa'' "Crow" to some [[Koori]] people in southeastern Australia.<ref>{{cite book|last=Mudrooroo|title=Aboriginal mythology: an A-Z spanning the history of aboriginal mythology from the earliest legends to the present day|publisher=HarperCollins|location=London|date=1994|page=27|isbn=1-85538-306-3}}</ref> The Boorong people of northwestern Victoria recalled that ''War'' (Canopus) was the brother of ''Warepil'' (Sirius), and that he brought fire from the heavens and introduced it to humanity. His wife was ''Collowgullouric War'' ([[Eta Carinae]]).<ref name=hamacher10>{{cite journal|last1=Hamacher|first1=Duane W. |last2=Frew|first2=David J. |date=2010|title= An Aboriginal Australian Record of the Great Eruption of Eta Carinae|journal=Journal of Astronomical History & Heritage |volume=13|issue=3|pages= 220–34|bibcode=2010JAHH...13..220H|arxiv = 1010.4610 }}</ref> The Pirt-Kopan-noot people of western Victoria tell of ''Waa'' "Crow" falling in love with a queen, ''Gneeanggar'' "Wedge-tailed Eagle" (Sirius) and her six attendants (the Pleiades). His advances spurned, he hears that the women are foraging for grubs and so transforms himself into a grub. When the women dig him out, he changes into a giant and carries her off.<ref>Mudroodoo, p. 55.</ref> The Kulin people know Canopus as ''Lo-an-tuka''.<ref name=hamacher10/> Objects in the sky are also associated with states of being for some tribes; the Wailwun of northern New South Wales know Canopus as ''Wumba'' "deaf", alongside Mars as ''Gumba'' "fat" and Venus as ''Ngindigindoer'' "you are laughing".<ref name="noctuary">{{cite book|last=Johnson|first=Diane|title=Night skies of aboriginal Australia: a noctuary|publisher=University of Sydney|location=Darlington, New South Wales|date=1998|page=[https://archive.org/details/nightskiesofabor0000john/page/84 84]|isbn=1-86451-356-X|url-access=registration|url=https://archive.org/details/nightskiesofabor0000john/page/84}}</ref> Tasmanian aboriginal lore holds that Canopus is ''Dromerdene'', the brother of ''Moinee''; the two fought and fell out of the sky, with ''Dromerdene'' falling into Louisa Bay in southwest Tasmania.<ref name="haynes2000">{{cite book|last=Haynes|first=Ros D.|title= Astronomy and the Dreaming: The Astronomy of the Aboriginal Australians. Astronomy Across Cultures: The History of Non-Western Astronomy|publisher=Kluwer Academic Publishers|date=2000|page=57|doi=10.1007/978-94-011-4179-6_3}}</ref> ===Legacy=== [[File:HMS Glory LOC ggbain.17135.jpg|thumb|right|[[Canopus-class battleship]] HMS Glory]] Canopus appears on the [[flag of Brazil]], symbolising the state of [[Goiás]].<ref>{{cite web |title=Astronomy of the Brazilian Flag |url=https://flagspot.net/flags/br_astro.html |publisher=FOTW Flags Of The World website }}</ref> Two U.S. Navy [[submarine tender]]s have been named after Canopus, the [[USS Canopus (AS-9)|first]] serving from 1922 to 1942 and the [[USS Canopus (AS-34)|second]] serving from 1965 to 1994. The [[Royal Navy]] built nine [[Canopus-class ship of the line|Canopus-class ships of the line]] in the early 19th century, and six {{Sclass|Canopus|battleship|1}}s which entered services between 1899 and 1902. There are at least two mountains named after the star: [[Mount Canopus]] in Antarctica; and Mount Canopus or Canopus Hill in [[Tasmania]], the location of the [[Canopus Hill Observatory|Canopus Hill astronomical observatory]]. {{clear}} ==See also== *[[List of brightest stars]] *[[List of most luminous stars]] *[[Dune (novel)]] ==References== {{Reflist|30em}} ===Bibliography=== * {{cite book | last = Makemson | first = Maud Worcester | date = 1941 | publisher = [[Yale University Press]] | title = The Morning Star Rises: an account of Polynesian astronomy | bibcode = 1941msra.book.....M }} * {{cite book |title=The Brightest Stars: Discovering the Universe through the Sky's Most Brilliant Stars |last=Schaaf |first=Fred |year=2008 |publisher=John Wiley & Sons |location=Hoboken, NJ |isbn=978-0-471-70410-2 }} 30cd98e20631d240912f0a4c2c6c03e68c62bf1d 350 349 2022-09-04T15:29:34Z SpaceMan 2 Canopus wikitext text/x-wiki {{short description|Bright giant star in the constellation of Carina}} {{Other uses}} {{Starbox begin | name=Canopus }} {{Starbox image | image=[[File:Canopus.jpg|255px]] | caption=An image of Canopus by [[Expedition 6]] }} {{Starbox observe | epoch=J2000 | constell=[[Carina (constellation)|Carina]] | pronounce={{IPAc-en|k|ə|ˈ|n|oʊ|p|ə|s}}<ref>{{OED|Canopus}}</ref> | ra={{RA|06|23|57.10988}}<ref name="van Leeuwen2007">{{cite journal | title=Validation of the new Hipparcos reduction | last1=van Leeuwen | first1=F. | journal=Astronomy and Astrophysics | volume=474 | issue=2 | pages=653–664 | date=2007 | arxiv=0708.1752 | bibcode=2007A&A...474..653V | doi=10.1051/0004-6361:20078357 | s2cid=18759600 }} [http://webviz.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b48255b3&-out.add=.&-source=I/311/hip2&recno=30362 Vizier catalog entry ]</ref> | dec={{DEC|-52|41|44.3810}}<ref name="van Leeuwen2007"/> | appmag_v=−0.74<ref name="Ducati 2002">{{cite journal | title=Catalogue of Stellar Photometry in Johnson's 11-color system | last1=Ducati | first1=J. R. | journal=CDS/ADC Collection of Electronic Catalogues | volume=2237 | pages=0 | date=2002 | bibcode=2002yCat.2237....0D }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b360304a&-out.add=.&-source=II/237/colors&recno=1155 Vizier catalog entry ]</ref> }} {{Starbox character | type= | class=A9&nbsp;II<ref name=perkins>{{cite journal|bibcode=1989ApJS...69..301G|title=The early F-type stars – Refined classification, confrontation with Stromgren photometry, and the effects of rotation|journal=Astrophysical Journal Supplement Series|volume=69|pages=301|last1=Gray|first1=R. O.|last2=Garrison|first2=R. F.|year=1989|doi=10.1086/191315}}</ref><ref>{{cite journal|bibcode=1993ASPC...45...59L|title=A Spectroscopic Study of High Galactic Latitude F Supergiant Stars|journal=Luminous High-Latitude Stars. The International Workshop on Luminous High-Latitude Stars|volume=45|pages=59|last1=Lopez-Cruz|first1=O.|last2=Garrison|first2=R. F.|year=1993}}</ref> | b-v=+0.15<ref name="Ducati 2002"/> | u-b=+0.10<ref name="Ducati 2002"/> | variable= }} {{Starbox astrometry | radial_v={{val|20.3|0.5}}<ref name="Gontcharov 2007">{{cite journal | title=Pullkovo Compilation of Radial Velocities for 39495 Hipparcos stars in a common system | last1=Gontcharov | first1=G. A. | journal=Astronomy Letters | volume=32 | issue=1 | pages=759–771 | date=2007 | bibcode=2006AstL...32..759G | doi=10.1134/S1063773706110065|arxiv = 1606.08053 | s2cid=119231169 }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b5f60fbd&-out.add=.&-source=III/252/table8&recno=9232 Vizier catalog entry ]</ref> | prop_mo_ra=19.93<ref name="van Leeuwen2007"/> | prop_mo_dec=23.24<ref name="van Leeuwen2007"/> | parallax=10.55 | p_error=0.56 | parallax_footnote=<ref name="van Leeuwen2007"/> | absmag_v=–5.71<ref name=smiljanic2006/> |arxiv = 1606.08053 }} {{Starbox detail | metal_fe=–0.07<ref name=smiljanic2006/> | mass={{Val|8.0|0.3}}<ref name=vlti>{{cite journal|bibcode=2013MNRAS.434..437C|arxiv=1306.3288|title=Fundamental parameters of 16 late-type stars derived from their angular diameter measured with VLTI/AMBER|journal=Monthly Notices of the Royal Astronomical Society|volume=434|issue=1|pages=437–450|last1=Cruzalèbes|first1=P.|last2=Jorissen|first2=A.|last3=Rabbia|first3=Y.|last4=Sacuto|first4=S.|last5=Chiavassa|first5=A.|last6=Pasquato|first6=E.|last7=Plez|first7=B.|last8=Eriksson|first8=K.|last9=Spang|first9=A.|last10=Chesneau|first10=O.|year=2013|doi=10.1093/mnras/stt1037|s2cid=49573767}}</ref>&nbsp;(2013)<br/>{{val|10.1|0.1}}<ref name=Tetzlaff2011/>&nbsp;(2011) | radius={{Val|71|4}}<ref name=vlti/>&nbsp;(2013)<br>{{val|73.3|5.2}}<ref name=DomicianoDeSouza>{{cite journal|doi=10.1051/0004-6361/202140478|title=Refined fundamental parameters of Canopus from combined near-IR interferometry and spectral energy distribution|year=2021|last1=Domiciano De Souza|first1=A.|last2=Zorec|first2=J.|last3=Millour|first3=F.|last4=Le Bouquin|first4=J.-B.|last5=Spang|first5=A.|last6=Vakili|first6=F.|journal=Astronomy & Astrophysics|volume=654|pages=A19|arxiv=2109.07153|bibcode=2021A&A...654A..19D|s2cid=237513623}}</ref>&nbsp;(2021) | gravity={{Val|1.70|0.05}}<ref name=DomicianoDeSouza/> | rotational_velocity=9<ref name=ayres2018/> | rotation={{val|298|u=days|p=≥}}<ref name=Testa2004/> | luminosity=10,700<ref name=vlti/> | temperature=7,400<ref name=ayres2018>{{cite journal |bibcode=2018ApJ...854...95A |title=Cracking the Conundrum of F-supergiant Coronae |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |year=2018 |volume=854 |issue=2 |page=95 |doi=10.3847/1538-4357/aaa6d7 |arxiv=1802.02552 |s2cid=119101035 }}</ref> | age_myr = {{val|25.1|2.5}}<ref name=Tetzlaff2011>{{cite journal | title=A catalogue of young runaway Hipparcos stars within 3 kpc from the Sun | last1=Tetzlaff | first1=N. | last2=Neuhäuser | first2=R. | last3=Hohle | first3=M. M. | journal=Monthly Notices of the Royal Astronomical Society | volume=410 | issue=1 | pages=190–200 | date=January 2011 | doi=10.1111/j.1365-2966.2010.17434.x | arxiv=1007.4883 | bibcode=2011MNRAS.410..190T | s2cid=118629873 }}</ref> }} {{Starbox catalog | names={{odlist | name=Suhayl | name2=Suhel | name3=Suhail | B=α Carinae | CPD=−52°1941 | FK5=245 | HD=45348 | HIP=30438 | HR=2326 | SAO=234480| GC=8302 }}<ref name=SIMBAD>{{cite simbad | title=alf Car | access-date=2019-03-09 }}</ref> }} {{Starbox reference | Simbad=canopus }} {{Starbox end}} '''Canopus''' is the brightest star in the southern [[constellation]] of [[Carina (constellation)|Carina]] and the [[list of brightest stars|second-brightest star]] in the [[night sky]]. It is also [[Bayer designation|designated]] '''α&nbsp;Carinae''', which is [[Latinisation of names|Latinised]] to '''Alpha&nbsp;Carinae'''. With a [[visual apparent magnitude]] of −0.74, it is outshone only by [[Sirius]]. Located around {{val|310|ul=light-years}} from the [[Sun]], Canopus is a [[bright giant]] of [[spectral type A9]], so it is essentially white when seen with the naked eye. It has a luminosity over 10,000 times the [[luminosity of the Sun]], is eight times as [[mass of the Sun|massive]], and has expanded to 71 times the [[Sun's radius]]. Its enlarged [[photosphere]] has an [[effective temperature]] of around {{val|7,400|fmt=commas|u=K}}. Canopus is undergoing [[stellar core|core]] [[helium fusion|helium burning]] and is currently in the so-called [[blue loop]] phase of its [[stellar evolution|evolution]], having already passed through the [[red-giant branch]] after exhausting the hydrogen in its core. Canopus is a [[X-ray astronomy|source of X-rays]], which are likely being emitted from its [[stellar corona|corona]]. The prominent appearance of Canopus means it has been the subject of mythological lore among many ancient peoples. Its proper name is generally considered to originate from the [[Greek mythology|mythological]] [[Canopus (mythology)|Canopus]], who was a navigator for [[Menelaus]], king of [[Sparta]]. The [[acronychal rising]] marked the date of the Ptolemaia festival in Egypt. In ancient India, it was named [[Agastya]] after the revered [[Vedas|Vedic]] sage. For Chinese astronomers, it was known as the [[Old Man of the South Pole]]. ==Nomenclature== The name ''Canopus'' is a Latinisation of the [[Ancient Greek]] name Κάνωβος/Kanôbos, recorded in Claudius Ptolemy's ''[[Almagest]]'' (c.150 AD). Eratosthenes used the same spelling.<ref name="ridpathCr"/> Hipparchos wrote it as Κάνωπος. [[John Flamsteed]] wrote Canobus,<ref>{{cite book|last=Flamsteed|first=John|title=Atlas coelestis|location=London, United Kingdom|date=1729|pages=Constellation Map of Southern Hemisphere|url=http://lhldigital.lindahall.org/u?/astro_atlas,1191}}</ref> as did [[Edmond Halley]] in his 1679 ''Catalogus Stellarum Australium''.<ref name="Halley 1679">{{cite book|last=Halley|first=Edmond|title=Catalogus stellarum australium; sive, Supplementum catalogi Tychenici, exhibens longitudines et latitudines stellarum fixarum, quae, prope polum Antarcticum sitae, in horizonte Uraniburgico Tychoni inconspicuae fuere, accurato calculo ex distantiis supputatas, & ad annum 1677 completum correctas...Accedit appendicula de rebus quibusdam astronomicis|publisher=T. James|location=London|date=1679|pages=30|url=http://babel.hathitrust.org/cgi/pt?id=mdp.39015007000170;view=1up;seq=41;size=150}}</ref> The name has two possible derivations, both listed in [[Richard Hinckley Allen]]'s seminal ''[[Star Names: Their Lore and Meaning]]''. * [[Argo Navis]] was the ship used by [[Jason]] and the Argonauts in the legend of the [[Trojan War]]. The brightest star in the constellation was given the name of a ship's pilot from another Greek legend: [[Canopus (mythology)|Canopus]], pilot of [[Menelaus]]' ship on his quest to retrieve [[Helen of Troy]] after she was taken by [[Paris (mythology)|Paris]].<ref name="hinkley63">{{cite book|first=Richard Hinckley|last=Allen|author-link=Richard Hinckley Allen|date=1963|orig-year=1899|title=Star Names: Their Lore and Meaning|pages=[https://archive.org/details/starnamestheirlo00alle/page/67 67–72]|edition=Revised|publisher=Dover Publications|location=New York|isbn=0-486-21079-0|url-access=registration|url=https://archive.org/details/starnamestheirlo00alle/page/67}}</ref> * A ruined ancient Egyptian port named [[Canopus, Egypt|Canopus]] lies near the mouth of the [[Nile]], site of the [[Battle of the Nile]]. It is speculated that its name is derived from the Egyptian [[Coptic language|Coptic]] ''Kahi Nub'' ("Golden Earth"), which refers to how Canopus would have appeared near the horizon in [[ancient Egypt]], reddened by atmospheric extinction from that position.<ref name="hinkley63"/><ref name=lynn1905>{{cite journal |bibcode=1905Obs....28..289L |title=The brightest fixed star and its name |last1=Lynn |first1=W. T. |journal=The Observatory |year=1905 |volume=28 |page=289 }}</ref> In 2016, the [[International Astronomical Union]] organized a [[IAU Working Group on Star Names|Working Group on Star Names]] (WGSN) to catalog and standardize proper names for stars.<ref name="WGSN">{{cite web | url=https://www.iau.org/science/scientific_bodies/working_groups/280/ | title=IAU Working Group on Star Names (WGSN) | website=iau.org | publisher=[[International Astronomical Union]] | access-date=22 May 2016}}</ref> The WGSN's first bulletin of July 2016 included a table of the first two batches of names approved by the WGSN, which included ''Canopus'' for this star.<ref name="WGSN1">{{cite web | url=https://www.iau.org/static/science/scientific_bodies/working_groups/280/WGSN_bulletin1.pdf | title=Bulletin of the IAU Working Group on Star Names, No. 1 | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06 }}</ref> Canopus is now included in the ''IAU Catalog of Star Names''.<ref name="IAU-CSN">{{cite web | url=https://www.iau.org/public/themes/naming_stars/ | title=IAU Catalog of Star Names | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06}}</ref> Canopus traditionally marked the rudder of the ship [[Argo Navis]].<ref>{{cite journal | title = On Frederick de Houtman's Catalogue of Southern Stars, and the Origin of the Southern Constellations | last1= Knobel|first1=E. B. |journal = [[Monthly Notices of the Royal Astronomical Society]] | volume= 77| issue= 5 | pages=414–432 [422] | bibcode = 1917MNRAS..77..414K |date=1917 | doi=10.1093/mnras/77.5.414| doi-access=free }}</ref> German celestial cartographer [[Johann Bayer]] gave it—as the brightest star in the constellation—the [[Bayer designation|designation]] of ''α&nbsp;Argus'' ([[Latinisation of names|Latinised]] to ''Alpha Argus'') in 1603. In 1763, French astronomer [[Nicolas Louis de Lacaille]] divided the huge constellation into three smaller ones,<ref name=Glass2012>{{cite book | title=Nicolas-Louis De La Caille, Astronomer and Geodesist | first=Ian Stewart | last=Glass | date=November 17, 2012 | page=73 | isbn=9780191649608 | publisher=OUP Oxford | url=https://www.google.com/books/edition/Nicolas_Louis_De_La_Caille_Astronomer_an/eZjlHAIBeRAC?hl=en&gbpv=1&pg=PT73 }}</ref> and hence Canopus became ''α&nbsp;Carinae'' ([[Latinisation of names|Latinised]] to ''Alpha Carinae''). It is listed in the [[Bright Star Catalogue]] as HR 2326, the [[Henry Draper Catalogue]] as HD 45348, and the [[Hipparcos catalogue]] as HIP 30438.<ref name=SIMBAD/> Flamsteed did not number this southern star, but [[Benjamin Apthorp Gould]] gave it the number 7 (7 G. Carinae) in his ''Uranometria Argentina''.<ref name=Gould1878>{{cite journal | title=Uranometria Argentina: Brightness and position of every fixed star, down to the seventh magnitude, within one hundred degrees of the South Pole; with atlas | last=Gould | first=Benjamin Apthorp | journal=Resultados del Observatorio Nacional Argentino | volume=1 | page=140 | date=1878 | bibcode=1879RNAO....1....1G }}</ref> An occasional name seen in English is ''Soheil'', or the feminine Soheila; in Turkish is ''Süheyl'', or the feminine Süheyla, from the Arabic name for several bright stars, سهيل ''suhayl'',<ref name="hinkley63"/> and Canopus was known as Suhel {{IPAc-en|'|s|uː|h|E|l}} in medieval times.<ref name=kunitzsch/> Alternative spellings include Suhail, Souhail, Suhilon, Suheyl, Sohayl, Suhayil, Shoel, Sohil, Soheil, Sahil, Suhayeel, Sohayil, Sihel, and Sihil.<ref name="hinkley63"/> An alternative name was ''Wazn'' "weight" or ''Haḍar'' "ground", possibly related to its low position near the horizon.<ref name="hinkley63"/> Hence comes its name in the ''[[Alfonsine tables]]'', Suhel ponderosus, a Latinization of ''Al Suhayl al Wazn''.<ref name="hinkley63"/> Its Greek name was revived during the [[Renaissance]].<ref name=kunitzsch>{{cite book |last1=Kunitzsch|first1=Paul |last2=Smart|first2=Tim |date = 2006|title = A Dictionary of Modern star Names: A Short Guide to 254 Star Names and Their Derivations |edition = 2nd rev. |publisher = Sky Publishing Corporation |location = Cambridge, Massachusetts |isbn = 978-1-931559-44-7 |page = 23}}</ref> ==Observation== [[File:Carina constellation map.svg|thumb|left|The constellation [[Carina (constellation)|Carina]] with Canopus towards the right (west)]] The Spanish Muslim astronomer [[Ibn Rushd]] went to [[Marrakesh]] (in Morocco) to observe the star in 1153, as it was invisible in his native [[Córdoba, Spain|Córdoba]], [[Al-Andalus]]. He used the different visibility in different latitudes to argue that the [[Spherical Earth|earth is round]], following [[Spherical Earth#Aristotle|Aristotle's argument]] which held that such an observation was only possible if the earth was a relatively small sphere.<ref name=ibn_rushd>{{cite encyclopedia|first1=Juan|last1=Vernet|author-link1=Juan Vernet|first2=Julio|last2=Samsó|author-link2=Julio Samsó |title=The development of Arabic science in Andalusia |page=264|editor=[[Roshdi Rashed]]|encyclopedia=Encyclopedia of the History of Arabic Science | date=1996|publisher=Routledge|isbn=978-0-415-12410-2|oclc=912501823}}</ref> English explorer [[Robert Hues]] brought Canopus to the attention of European observers in his 1592 work ''Tractatus de Globis'', along with [[Achernar]] and [[Alpha Centauri]], noting:<blockquote>"Now, therefore, there are but three [[First-magnitude star|Stars of the first magnitude]] that I could perceive in all those parts which are never seene here in England. The first of these is that bright Star in the sterne of [[Argo Navis|Argo]] which they call Canobus. The second is in the end of [[Eridanus (constellation)|Eridanus]]. The third is in the right foote of the [[Centaurus|Centaure]]."<ref>Knobel, p. 416.</ref></blockquote> [[File:Vela and Surrounding Constellations (ground-based image).jpg|right|thumb|Wide angle view showing Canopus and other prominent stars with the Milky Way|alt=A field of stars against the Milky Way background with the prominent stars and constellations labelled]] In the [[Southern Hemisphere]], Canopus and [[Sirius]] are both visible high in the sky simultaneously, and reach a [[meridian (astronomy)|meridian]] just {{val|21|u=minutes}} apart. Brighter than [[first-magnitude star|first magnitude]], Canopus can be seen by naked eye in the early twilight. Mostly visible in mid to late summer in the Southern Hemisphere, Canopus [[Culmination|culminates]] at midnight on December 27,<ref name="motz" /> and at 9 PM on February 11.<ref name="Schaaf257">Schaaf, p. 257.</ref> When seen from latitudes south of {{DEC|37|18}}&nbsp;S, Canopus is a [[circumpolar star]]. Since Canopus is so far south in the sky, it never rises in mid- to far-northern latitudes; in theory the northern limit of visibility is latitude {{DEC|37|18}} north. This is just south of [[Athens]], [[Richmond, Virginia]] (USA), and [[San Francisco]], and very close to [[Seville]] and [[Agrigento]]. It is almost exactly the latitude of [[Lick Observatory]] on [[Mount Hamilton (California)|Mt. Hamilton, California]], from which it is readily visible because of the effects of elevation and [[atmospheric refraction]], which add another degree to its apparent altitude. Under ideal conditions, it can be spotted as far north as latitude {{DEC|37|31}} from the Pacific coast.<ref>D. Gieringer, "Exploring the Tropic of Canopus", ''Astronomy'', December 1985, p.24.</ref> Another northernmost record of visibility came from [[Mount Nemrut]] in Turkey, latitude {{DEC|37|59}}.<ref>{{cite web |last1=Tezel |first1=Tunç |author-link=Tunç Tezel |url=http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |title=Zodiacal Light and Nemrut Heritage |work=The World At Night (TWAN) |access-date=17 March 2014 |date=8 Oct 2013 |archive-url=https://web.archive.org/web/20140317134955/http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |archive-date=17 March 2014 |url-status=dead }}</ref> It is more easily visible in places such as the Gulf Coast and Florida, and the island of [[Crete]] (Greece) where the best season for viewing it around 9 p.m. is during late January and early February.<ref name="motz">{{cite book|last1=Motz|first1=Lloyd|last2=Nathanson|first2=Carol|title=The Constellations: An Enthusiast's Guide to the Night Sky|publisher=Aurum Press|location=London, United Kingdom|date=1991|pages=376–77|isbn=1-85410-088-2}}</ref> Canopus has a B–V [[color index]] of +0.15—where 0 is a blue-white—indicating it is essentially white, although it has been described as yellow-white. Canopus' spectral type has been given as F0 and the incrementally warmer A9. It is less yellow than [[Altair]] or [[Procyon]], with indices measured as 0.22 and 0.42, respectively.<ref name=Hoffleit1991>{{cite book | title=Bright Star Catalogue | edition=5th Revised | last1=Hoffleit | first1=D. | last2=Warren Jr. | first2=W. H. | date=1991 | publisher=[[Centre de Données astronomiques de Strasbourg|CDS]] }}</ref> Some observers may have perceived Canopus as yellow-tinged because it is low in the sky and hence subject to atmospheric effects.<ref name="Schaaf112">Schaaf, pp. 112–13.</ref> [[Patrick Moore]] said that it never appeared anything but white to him.<ref name="moore2000">{{cite book | first1=Patrick | last1=Moore | title=Exploring the night sky with binoculars | edition=4th | publisher=Cambridge University Press | year=2000 | isbn=9780521793902 | page=[https://archive.org/details/exploringnightsk00moor/page/69 69] | url=https://archive.org/details/exploringnightsk00moor| url-access=registration }}</ref> The [[bolometric correction]] for Canopus is 0.00,<ref name=smiljanic2006/> indicating that the visual [[absolute magnitude]] and bolometric absolute magnitude are equal. Canopus was previously proposed to be a member of the [[Scorpius–Centaurus association]], however it is not located near the subgroups of that association, and has not been included as a Sco-Cen member in kinematic studies that used [[Hipparcos]] astrometric data.<ref name="deZeeuw">{{cite journal|last1=de Zeeuw|first1=P.T. |last2=Hoogerwerf|first2=R. |last3=de Bruijne|first3=J.H.J |last4=Brown|first4=A.G.A |last5=Blaauw|first5=A. |date=1999|title=A HIPPARCOS Census of the Nearby OB Associations |journal=The Astronomical Journal |volume=117 |issue=1 |pages=354–399|bibcode=1999AJ....117..354D |doi=10.1086/300682|arxiv = astro-ph/9809227 |s2cid=16098861 }}</ref> Canopus is not thought to be a member of any nearby young stellar groups.<ref name=mamajek>{{cite journal | url=https://figshare.com/articles/Canopus_B_A_Candidate_Common_Proper_Motion_Companion_to_the_Second_Brightest_Star/1132696 | title=Canopus B: A Candidate Common Proper Motion Companion to the Second Brightest Star | last=Mamajek | first=Eric | year=2014 | publisher=Figshare | doi=10.6084/m9.figshare.1132696.v3 | access-date=2020-09-10 }}</ref> In 2014, astronomer Eric Mamajek reported that an extremely magnetically active M dwarf (having strong coronal X-ray emission), 1.16 degrees south of Canopus, appears to share a [[common proper motion]] with Canopus. The projected separation of the M dwarf 2MASS J06234738-5351131 ("Canopus B") is approximately 1.9 parsecs. However, despite this large separation, it is still within the estimated tidal radius (2.9 parsecs) for the massive star Canopus.<ref name="mamajek"/> No star closer than Canopus is more luminous than it, and it has been the brightest star in Earth's night sky during three epochs over the past four million years. Other stars appear brighter only during relatively temporary periods, during which they are passing the Solar System much closer than Canopus. About 90,000 years ago, [[Sirius]] moved close enough that it became brighter than Canopus, and that will remain so for another 210,000 years. But in 480,000 years, as Sirius moves further away and appears fainter, Canopus will once again be the brightest, and will remain so for a period of about 510,000 years.<ref name="tomkin98">{{cite journal|last=Tomkin|first=Jocelyn|date=April 1998|title=Once and Future Celestial Kings|journal=Sky and Telescope|volume=95|issue=4|pages=59–63|bibcode=1998S&T....95d..59T}}</ref><!-- this all comes from same paper --> ===Role in navigation=== The southeastern wall of the [[Kaaba]] in [[Mecca]] is aligned with the rising point of Canopus, and is also named ''Janūb''.<ref>{{cite book|author=George Nicholas Atiyeh|title=The Book in the Islamic World: The Written Word and Communication in the Middle East|url=https://books.google.com/books?id=t4LEfpCW_kQC|date=1 January 1995|publisher=SUNY Press|isbn=978-0-7914-2473-5}}</ref> The [[Negev Bedouin|Bedouin]] people of the [[Negev]] and [[Sinai Peninsula|Sinai]] knew Canopus as ''Suhayl'', and used it and [[Polaris]] as the two principal stars for navigation at night. Because it disappears below the horizon in those regions, it became associated with a changeable nature, as opposed to always-visible Polaris, which was circumpolar and hence 'steadfast'.<ref>{{cite journal |last=Bailey |first=Clinton |date=1974 |title=Bedouin Star-Lore in Sinai and the Negev |journal=Bulletin of the School of Oriental and African Studies, University of London |volume=37 |issue=3 |pages=580–96 |type=abstract |doi=10.1017/S0041977X00127491 |jstor=613801|s2cid=131527348 }}</ref> The south [[celestial pole]] can be approximately located using Canopus and another bright star, [[Achernar]], as the three make an [[equilateral triangle]]. Canopus sits on an imaginary line that extends {{DEC|36}} one way to Sirius and {{DEC|37}} to the south celestial pole.<ref>{{Cite book| last1 = Heifetz| first1 = Milton| last2 = Tirion| first2 = Wil| title = A Walk Through the Heavens: A Guide to Stars and Constellations and Their Legends | date = 2007| publisher = [[Cambridge University Press]]| location = Cambridge | page = 38 | isbn=978-1-139-46138-2}}</ref> Canopus's brightness and location well off the [[ecliptic]] make it useful for space navigation. Many spacecraft carry a special camera known as a "Canopus [[star tracker|Star Tracker]]" plus a Sun sensor for [[Orientation (geometry)|attitude]] determination. [[Mariner 4]] used Canopus for [[Spin-stabilisation|second axis stabilisation]] (after locking on the Sun) in 1964, the first time a star had been used.<ref>{{cite book |last1=United States. National Aeronautics and Space Administration. Scientific and Technical Information Division |title=Astronautics and Aeronautics, 1964: Chronology on Science, Technology and Policy |date=1965 |publisher=Scientific and Technical Information Division, National Aeronautics and Space Administration |page=398 |url=https://books.google.com/books?id=ckkCAAAAIAAJ&pg=PA398}}</ref> ==Spectrum== Canopus was little-studied by western scientists before the 20th century. It was given a spectral class of F in 1897, an early use of this extension to [[Secchi class]] I, applied to those stars where the hydrogen lines are relatively weak and the [[calcium K line]] relatively strong.<ref>{{cite journal |bibcode=1897ApJ.....6..349P |title=Spectra of bright southern stars |last1=Pickering |first1=E. C. |last2=Cannon |first2=A. J. |journal=The Astrophysical Journal |year=1897 |volume=6 |page=349 |doi=10.1086/140407 }}</ref> It was given as a standard star of F0 in the [[Henry Draper Catalogue]], with the spectral type F0 described as having hydrogen lines half the strength of an A0 star and the calcium K line three times as strong as Hδ.<ref name=hd>{{cite journal |bibcode=1918AnHar..92....1C |title=The Henry Draper catalogue : 4h, 5h and 6h |last1=Cannon |first1=Annie Jump |last2=Pickering |first2=Edward Charles |journal=Annals of Harvard College Observatory |year=1918 |volume=92 |page=1 }}</ref> American astronomer [[Jesse L. Greenstein|Jesse Greenstein]] was interested in stellar spectra and used the newly built [[Otto Struve Telescope]] at [[McDonald Observatory]] to analyze the star's spectrum in detail.<ref>{{cite book |last1=Trimble |first1=Virginia | first2= Thomas R. |last2=Williams | first3= Katherine | last3=Bracher| first4= Richard | last4=Jarrell| first5=Jordan D.| last5= Marché| first6=F. Jamil | last6=Ragep |title=Biographical Encyclopedia of Astronomers |date=2007 |publisher=Springer Science & Business Media |location=New York, New York |isbn=978-0-387-30400-7 |page=438 |url=https://books.google.com/books?id=t-BF1CHkc50C&pg=PA438}}</ref> In a 1942 paper, he reported that the spectrum is dominated by strong broad hydrogen lines. There are also [[absorption line]]s of carbon, nitrogen, oxygen, sulphur, iron, and many ionised metals.<ref name=greenstein1942>{{cite journal |bibcode=1942ApJ....95..161G |title=The Spectrum of α Carinae |last1=Greenstein |first1=Jesse L. |journal=The Astrophysical Journal |year=1942 |volume=95 |page=161 |doi=10.1086/144382 }}</ref> It was studied in the [[ultraviolet]] by an early astronomical satellite, [[Gemini XI]] in 1966. The UV spectra were considered to be consistent with an F0 [[Supergiant star|supergiant]] having a temperature of {{val|6,900|fmt=commas|u=K}}, the accepted parameters for Canopus at the time.<ref name=kondo1970>{{cite journal |bibcode=1970ApJ...159..927K |title=Ultraviolet Spectrophotometry of Canopus from Gemini XI |last1=Kondo |first1=Y. |last2=Henize |first2=K. G. |last3=Kotila |first3=C. L. |journal=The Astrophysical Journal |year=1970 |volume=159 |page=927 |doi=10.1086/150370 }}</ref> New Zealand-based astronomers [[John Hearnshaw]] and Krishna Desikachary examined the spectrum in greater detail, publishing their results in 1982.<ref>{{cite journal |title=The spectrum of Canopus | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 198 | year= 1982 | issue= 2 | pages= 311–320 | doi= 10.1093/mnras/198.2.311 | bibcode=1982MNRAS.198..311H| doi-access= free }}</ref><ref>{{cite journal |title=The spectrum of Canopus II - Analysis and composition | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 201 | year= 1982 | issue= 3 | pages= 707–721 | doi= 10.1093/mnras/201.3.707 | bibcode=1982MNRAS.201..707D| doi-access= free }}</ref> When [[luminosity class]]es were added to the MK spectral classification scheme, Canopus was assigned class Iab indicating an intermediate luminosity supergiant. This was based on the relative strengths of certain spectral lines understood to be sensitive to the luminosity of a star.<ref name=devaucoleurs>{{cite journal|title=Spectral types and luminosities of B, A and F southern stars|author=de Vaucouleurs, A.|journal=Monthly Notices of the Royal Astronomical Society|volume=117|page=449|date=1957|issue=4|bibcode=1957MNRAS.117..449D|doi=10.1093/mnras/117.4.449|doi-access=free}}</ref> In the [[Bright Star Catalogue]] 5th edition it is given the spectral class F0II, the luminosity class indicating a [[bright giant]].<ref name=bsc>{{cite book |bibcode=1991bsc..book.....H |year=1991 |title=The Bright star catalogue |last1=Hoffleit |first1=Dorrit |last2=Jaschek |first2=Carlos }}</ref> [[Balmer line]] profiles and oxygen line strengths indicate the size and luminosity of Canopus.<ref name=kovtyukh2012>{{cite journal |bibcode=2012MNRAS.423.3268K |title=Accurate luminosities from the oxygen λ7771-4 Å triplet and the fundamental parameters of F-G supergiants |last1=Kovtyukh |first1=V. V. |last2=Gorlova |first2=N. I. |last3=Belik |first3=S. I. |journal=Monthly Notices of the Royal Astronomical Society |year=2012 |volume=423 |issue=4 |page=3268 |doi=10.1111/j.1365-2966.2012.21117.x |arxiv=1204.4115 |s2cid=118683158 }}</ref> When the effects of stellar rotation speed on spectral lines are accounted for, the MK spectral class of Canopus is adjusted to A9II.<ref name=perkins/> Its spectrum consists mostly of absorption lines on a visible [[continuous spectrum|continuum]], but some emission has been detected. For example, the [[calcium K line]] have weak emission wings on each side of the strong central absorption line, first observed in 1966. The emission line profiles are usually correlated with the luminosity of the star as described by the [[Wilson-Bappu effect]], but in the case of Canopus they indicate a luminosity much lower than that calculated by other methods.<ref name=warner1966>{{cite journal|title=CA II emission in the spectrum of Canopus|journal=The Observatory |volume=86 |pages=82|date=April 1966|last=Warner |first=B. |bibcode=1966Obs....86...82W }}</ref> More detailed observations have shown that the emission line profiles are variable and may be due to [[plage (astronomy)|plage]] areas on the surface of the star. Emission can also be found in other lines such as the h and k lines of ionised magnesium.<ref name=bappu1984>{{cite journal |bibcode=1984BASI...12..196B |title=CA II K emission in Canopus |last1=Bappu |first1=M. K. V. |last2=Mekkaden |first2=M. V. |last3=Rao |first3=N. K. |journal=Bulletin of the Astronomical Society of India |year=1984 |volume=12 |page=196 }}</ref> ==Distance== Before the launch of the [[Hipparcos]] satellite telescope, distance estimates for Canopus varied widely, from 96 [[light-year]]s to 1200 light-years. The closer distance was derived from parallax measurements of around {{val|33|ul=mas}}.<ref name=vandekamp1943>{{cite journal |title=Note on the Parallax of Canopus|journal=Popular Astronomy |volume=51 |date=1943 |page=172 |last=van de Kamp |first=Peter|bibcode=1943PA.....51..172V }}</ref> The larger distance derives from the assumption of a very bright [[absolute magnitude]] for Canopus.<ref name=vanzyl>{{cite book|author=J.E. van Zyl|title=Unveiling the Universe: An Introduction to Astronomy|url=https://books.google.com/books?id=Cj7uBwAAQBAJ&pg=PA184|date=6 December 2012|publisher=Springer Science & Business Media|isbn=978-1-4471-1037-8|pages=184–}}</ref> Hipparcos established Canopus as being {{val|310|u=light-years}} ({{val|95|ul=parsecs}}) from the [[Solar System]]; this is based on its 2007 [[parallax]] measurement of {{Val|10.43|0.53|ul=mas}}.<ref name="van Leeuwen2007"/> At 95 parsecs, the [[interstellar extinction]] for Canopus is low at 0.26 magnitudes.<ref name=DomicianoDeSouza/> Canopus is too bright to be included in the normal observation runs of the [[Gaia satellite]] and there is no published Gaia parallax for it.<ref name=dr2>{{cite DR2}}</ref> At present the star is drifting further away from the Sun with a [[radial velocity]] of 20&nbsp;km/s. Some 3.1&nbsp;million years ago it made the closest approach to the Sun at a distance of about {{convert|52.87|pc|ly|0|adj=ri0|order=flip|abbr=on|lk=off}}. Canopus is orbiting the Milky Way with a heliocentric velocity of 24.5&nbsp;km/s and a low [[orbital eccentricity|eccentricity]] of 0.065.<ref name=Anderson2012>{{citation | last1=Anderson | first1=E. | last2=Francis | first2=Ch. | title=XHIP: An extended hipparcos compilation | journal=Astronomy Letters | volume=38 | issue=5 | pages=331 | year=2012 | bibcode=2012AstL...38..331A | arxiv=1108.4971 | doi=10.1134/S1063773712050015 | s2cid=119257644 | postscript=. }}</ref> ==Physical characteristics== [[File:Constellation_Carina.jpg|thumb|right|upright|Canopus is the brightest star in the constellation of Carina (top).]] The [[absorption line]]s in the spectrum of Canopus shift slightly with a period of {{val|6.9|u=days}}. This was first detected in 1906 and the [[doppler effect|Doppler]] variations were interpreted as orbital motion.<ref name=curtis1907>{{cite journal |bibcode=1907PASP...19R.259C |title=The orbits of the spectroscopic binaries alpha Carinae, kappa Velorum, and alpha Pavonis |last1=Curtis |first1=H. D. |journal=Publications of the Astronomical Society of the Pacific |year=1907 |volume=19 |page=259 |doi=10.1086/121781 }}</ref> An orbit was even calculated, but no such companion exists and the small radial velocity changes are due to movements in the atmosphere of the star. The maximum observed [[radial velocities]] are only 0.7 to {{val|1.6|ul=km/s}}. Canopus also has a magnetic field that varies with the same period, detected by the [[Zeeman splitting]] of its spectral lines.<ref name=weiss1986>{{cite journal |bibcode=1986A&A...160..243W | title=The magnetic field of Canopus | last=Weiss | first=W. W. | journal= Astronomy and Astrophysics |volume= 160|pages= 243–250 | year=1986}}</ref> Canopus is bright at [[microwave]] wavelengths, one of the few F-class stars to be detected by radio.<ref name=gudel2002>{{cite journal |bibcode=2002ARA&A..40..217G |title=Stellar Radio Astronomy: Probing Stellar Atmospheres from Protostars to Giants |last1=Güdel |first1=Manuel |journal=Annual Review of Astronomy and Astrophysics |year=2002 |volume=40 |pages=217–261 |doi=10.1146/annurev.astro.40.060401.093806 |arxiv=astro-ph/0206436 |s2cid=53633983 }}</ref> The [[rotation period]] of the star is not accurately known, but may be over three hundred days.<ref name=Testa2004>{{cite journal | title=The Density of Coronal Plasma in Active Stellar Coronae | last1=Testa | first1=Paola | last2=Drake | first2=Jeremy J. | last3=Peres | first3=Giovanni | journal=The Astrophysical Journal | volume=617 | issue=1 | pages=508–530 | date=December 2004 | doi=10.1086/422355 | arxiv=astro-ph/0405019 | bibcode=2004ApJ...617..508T | s2cid=17532089 }}</ref> The [[projected rotational velocity]] has been measured at 9&nbsp;km/s.<ref name=ayres2018/> An early [[Interferometry|interferometric]] measurement of its [[angular diameter]] in 1968 gave a [[Limb darkening|limb-darkened]] value of {{val|6.86|ul=mas}}, close to the accepted modern value.<ref>{{cite journal |bibcode=1968ARA&A...6...13B |title=Measurement of Stellar Diameters |last1=Brown |first1=R. Hanbury |journal=Annual Review of Astronomy and Astrophysics |year=1968 |volume=6 |page=13 |doi=10.1146/annurev.aa.06.090168.000305 }}</ref> [[Very-long-baseline interferometry]] has been used to calculate Canopus' angular diameter at {{val|6.9|ul=mas}}. Combined with distance calculated from its Hipparcos parallax, this gives it a radius of 71 times [[Solar radius|that of the Sun]].<ref name=vlti/> If it were at the centre of the Solar System, it would extend 90% of the way to the orbit of [[Mercury (planet)|Mercury]].<ref name=Kalerstars>{{cite web|url=http://stars.astro.illinois.edu/sow/canopus.html|title=Canopus|last=Kaler|first=Jim|work=Stars|publisher=University of Illinois|access-date=8 July 2012|date=26 June 2009}}</ref> The radius and temperature relative to the Sun means that it is 10,700 times more luminous than the Sun, and its position in the [[H-R diagram]] relative to theoretical [[stellar evolution|evolutionary]] tracks means that it is {{Val|8.0|0.3}} times as massive as the Sun.<ref name=vlti/> Measurements of its shape find a 1.1° departure from spherical symmetry.<ref name=cruzalebes2015>{{cite journal |bibcode=2015MNRAS.446.3277C |title=Departure from centrosymmetry of red giants and supergiants measured with VLTI/AMBER |last1=Cruzalèbes |first1=P. |last2=Jorissen |first2=A. |last3=Chiavassa |first3=A. |last4=Paladini |first4=C. |last5=Rabbia |first5=Y. |last6=Spang |first6=A. |journal=Monthly Notices of the Royal Astronomical Society |year=2015 |volume=446 |issue=4 |page=3277 |doi=10.1093/mnras/stu2382 |doi-access=free }}</ref> Canopus is a source of [[X-ray astronomy|X-rays]], which are probably produced by its corona, magnetically heated to several million [[Kelvin]]. The temperature has likely been stimulated by fast rotation combined with strong convection percolating through the star's outer layers.<ref name=ness>{{cite journal|bibcode=2004A&A...427..667N|title=On the sizes of stellar X-ray coronae|journal=Astronomy and Astrophysics|volume=427|issue=2|pages=667–683|last1=Ness|first1=J.-U.|last2=Güdel|first2=M.|last3=Schmitt|first3=J. H. M. M.|last4=Audard|first4=M.|last5=Telleschi|first5=A.|year=2004|doi=10.1051/0004-6361:20040504|arxiv = astro-ph/0407231 |s2cid=11468731}}</ref> The soft X-ray sub-coronal X-ray emission is much weaker than the hard X-ray coronal emission. The same behaviour has been measured in other F-class supergiants such as [[α Persei]] and is now believed to be a normal property of such stars.<ref name=ayres2018/> == Evolution == The spectrum of Canopus indicates that it has exhausted its core hydrogen and [[stellar evolution|evolved]] away from the [[main sequence]], where it spent some 30 million years of its existence as a blue-white star <!-- source suggests B2V but may be too exact --> of around 10 solar masses.<ref>{{cite journal |last1=Peimbert |first1=M. |last2=Wallerstein | first2= G.| last3= Pilachowski | first3= C. A. |title=An upper limit for the deuterium abundance in Canopus |journal=Astronomy and Astrophysics |date=1981 |volume=104 |issue=1 |pages=72–74 | bibcode=1981A&A...104...72P}}</ref> The position of Canopus in the [[H–R diagram]] indicates that it is currently in the core-helium burning phase.<ref name=vlti/> It is an intermediate mass star that has left the [[red-giant branch]] before its core became [[degenerate matter|degenerate]] and is now in a [[blue loop]].<ref name=desouza>{{Cite journal | last1 = Domiciano De Souza | first1 = A. | last2 = Bendjoya | first2 = P. | last3 = Vakili | first3 = F. | last4 = Millour | first4 = F. | last5 = Petrov | first5 = R. G. | title = Diameter and photospheric structures of Canopus from AMBER/VLTI interferometry | doi = 10.1051/0004-6361:200810450 | journal = Astronomy and Astrophysics | volume = 489 | issue = 2 | pages = L5–L8 | year = 2008 |bibcode = 2008A&A...489L...5D | url = https://hal.archives-ouvertes.fr/hal-00316994/document | doi-access = free }}</ref> Models of stellar evolution in the blue loop phase show that the length of the blue loop is strongly affected by rotation and mixing effects inside the star. It is difficult to determine whether a star is currently evolving towards hotter temperature or returning to cooler temperatures, since the evolutionary tracks for stars with different masses overlap during the blue loops.<ref name=smiljanic2006>{{cite journal |bibcode=2006A&A...449..655S |title=CNO in evolved intermediate mass stars |last1=Smiljanic |first1=R. |last2=Barbuy |first2=B. |last3=De Medeiros |first3=J. R. |last4=Maeder |first4=A. |journal=Astronomy and Astrophysics |year=2006 |volume=449 |issue=2 |page=655 |doi=10.1051/0004-6361:20054377 |arxiv=astro-ph/0511329 |s2cid=3711409 }}</ref> Canopus lies on the warm side of the [[instability strip]] and does not pulsate like [[Cepheid variables]] of a similar luminosity.<ref name=ayres2011>{{cite journal |doi=10.1088/0004-637X/738/2/120 |title=The Curious Case of the Alpha Persei Corona: A Dwarf in Supergiant's Clothing? |year=2011 |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |volume=738 |issue=2 |page=120 |bibcode=2011ApJ...738..120A |doi-access=free }}</ref> However its atmosphere does appear to be unstable, showing strong signs of convection.<ref name=smiljanic2006/> Canopus may not be massive enough for its [[nuclear fusion|fusion]] chain to reach iron and trigger a core collapse and subsequent [[supernova]], instead eventually becoming a neon-oxygen [[white dwarf]].<ref name=Kalerstars/> ==Cultural significance == Canopus was known to the ancient Mesopotamians and given the name ''NUN-ki'' and represented the city of [[Eridu]] in the ''Three Stars Each'' [[Babylonian star catalogues]] and later [[MUL.APIN]] around 1100 BC.<ref>{{cite journal | last = Rogers | first = John H. | date = 1998 | title = Origins of the Ancient Constellations: I. The Mesopotamian Traditions | journal = Journal of the British Astronomical Association | volume = 108 | issue = 1 | pages = 9–28 | bibcode = 1998JBAA..108....9R}}</ref> Today, the star [[Sigma Sagittarii]] is known by the common name Nunki.<ref name=allen>{{citation | page=359 | first1=Richard Hinckley | last1=Allen | title=Star Names, their lore and meaning}}</ref> Canopus was not visible to the mainland [[Ancient Greece|ancient Greeks]] and [[Roman Empire|Romans]]; it was, however, visible to the [[ancient Egypt]]ians.<ref name="Schaaf107">Schaaf, p. 107.</ref> Hence [[Aratus]] did not write of the star as it remained below the horizon, while [[Eratosthenes]] and [[Ptolemy]]—observing from [[Alexandria]]—did, calling it ''Kanōbos''.<ref name=ridpathCr>{{cite web| url=http://www.ianridpath.com/startales/carina.htm | title=Carina |last1=Ridpath|first1=Ian|publisher=self-published |work=Star Tales | access-date= 10 December 2015}}</ref> An [[Egypt]]ian priestly poet in the time of [[Thutmose III]] mentions the star as ''Karbana,'' "the star which pours his light in a glance of fire, when he disperses the morning dew."<ref name="hinkley63" /> Under the [[Ptolemies]], the star was known as ''Ptolemaion'' ([[Ancient Greek|Greek]]: Πτολεμαῖον) and its [[acronychal rising]] marked the date of the Ptolemaia festival, which was held every four years, from 262 to 145 BC.<ref>[[Martianus Capella]] 7.838, {{cite journal | last1 = Hazzard | last2 = Fitzgerald | year = 1991 | title = The Regulation of the Ptolemeia | journal = Journal of the Royal Astronomical Society of Canada | volume = 85 | pages = 6–23 |bibcode = 1991JRASC..85....6H }}; Hazzard. 2000. ''Imagination of a Monarchy: Studies in Ptolemaic Propaganda'', 34–36.</ref> [[File:Statue of Averroes in Córdoba, Spain.jpg|thumb|upright|[[Averroes]], who used his 1153 observation of Canopus in [[Marrakesh]] while the star was invisible in his native Spain as an argument that the [[Spherical Earth|earth is round]].<ref name=ibn_rushd/>]] ===India=== In Indian [[Vedas|Vedic literature]], Canopus is associated with the sage [[Agastya]], one of the ancient [[siddhar]]s and [[rishi]]s (the others are associated with the stars of the [[Big Dipper]]).<ref name="Frawley 1993">{{cite book|last=Frawley|first=David|title=Gods, Sages and Kings: Vedic Secrets of Ancient Civilization|publisher=Motilal Banarsidass |location=New Delhi, India|date=1993}}</ref> To Agastya, the star is said to be the 'cleanser of waters', and its rising coincides with the calming of the waters of the [[Indian Ocean]]. It is thus considered the son of [[Pulastya]], son of [[Brahma]]. Canopus is described by [[Pliny the Elder]] and [[Gaius Julius Solinus]] as the largest, brightest and only source of [[starlight]] for navigators near [[Tamraparni]] island (ancient Sri Lanka) during many nights.<ref>{{cite book |last1=Pridham |first1=Charles |title=An Historical, Political, and Statistical Account of Ceylon and Its Dependencies |date=1849 |publisher=T. and W. Boone |page=7 |url=https://books.google.com/books?id=O4aqHOMSJdYC&pg=PR19-IA5|language=en}}</ref><ref name="Frawley 1993"/><ref>{{cite book |last1=Elder |first1=Pliny the |title=Delphi Complete Works of Pliny the Elder (Illustrated) |date=2015 |publisher=Delphi Classics |url=https://books.google.com/books?id=OrJ0CgAAQBAJ&pg=PA343|language=en}}</ref> ===China=== Canopus was described as Shou Xing, the Star of Longevity, in the ''Shiji'' ([[Records of the Grand Historian]]) completed in 94 BC by Chinese historian [[Sima Qian]].<ref name=fong83>{{cite journal | title=The Iconography of the Popular Gods of Happiness, Emolument, and Longevity (Fu Lu Shou) | first=Mary H. |last=Fong | journal=Artibus Asiae | volume= 44 | issue= 2/3 | year=1983| pages= 159–199 | doi= 10.2307/3249596| jstor=3249596 }}</ref> Drawing on sources from the [[Warring States period]], he noted it to be the southern counterpart of [[Sirius]],<ref name="IDP"/> and wrote of a sanctuary dedicated to it established by Emperor [[Qin Shi Huang]] between 221 and 210 BC. During the [[Han dynasty]], the star was auspicious, its appearance in the southern sky heralding peace and absence war.<ref name=fong83/> From the imperial capital [[Chang'an]], the star made a low transit across the southern sky, indicating true south to observers, and was often obscured by clouds.<ref name=baumann19>{{cite journal | title=The White Old Man: Géluk-Mongolian Canopus Allegory and the Existence of God | first=Brian | last=Baumann | journal= Central Asiatic Journal | volume= 62 | issue= 1 | year=2019| pages= 35–68 | doi=10.13173/centasiaj.62.1.0035| s2cid=213083544 }}</ref> During this time it was also equated with [[Old Man of the South Pole]] (in {{zh|c=南极老人|p=Nanji Lǎorén}})<ref name=fong83/> Under this name, Canopus appears (albeit misplaced northwards) on the medieval Chinese manuscript the [[Dunhuang Star Chart]], although it cannot be seen from the Chinese capital of [[Chang'an]].<ref name="IDP">{{cite journal|bibcode=2009JAHH...12...39B|arxiv=0906.3034|title=The Dunhuang Sky: A Comprehensive Study of the Oldest Known Star Atlas|volume=12|issue=1|pages=39–59|last1=Bonnet-Bidaud|first1=Jean-Marc |last2=Praderie|first2=Françoise |last3=Whitfield|first3=Susan |author-link=Susan Whitfield |journal=The International Dunhuang Project: The Silk Road Online|year=2009}}</ref> The Chinese astronomer [[Yi Xing]] had journeyed south to chart Canopus and other far southern stars in 724 AD.<ref>{{cite book|last=Needham|first=Joseph|title=Science and Civilisation in China: Volume 3, Mathematics and the Sciences of the Heavens and the Earth|publisher=Cambridge University Press|location=Cambridge, United Kingdom|date=1959|pages=274|isbn=0521058015}}</ref> Its personification as the Old Man Star was popularised in the [[Tang Dynasty]], where it appeared often in poetry and memorials. Later still, during the [[Ming Dynasty]], the star was established as one of the [[Sanxing (deities)|Three Stars]] (Fu Lo Shou), appearing frequently in art and literature of the time.<ref name=fong83/> This symbolism spread into neighbouring cultures in Asia.<ref name=baumann19/> In Japan, Canopus is known as ''Mera-boshi'' and ''Roujin-sei'' (the old man star),<ref>{{cite conference |url=http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |title=Stellar Iconology and Astronomical Folklore in Japan |author=Takao Ibaraki |book-title=International Planetarium Society (IPS) Conferences 1996 |publisher=International Planetarium Society |location=Osaka |date=14 July 1996 |access-date=25 February 2012 |url-status=dead |archive-url=https://web.archive.org/web/20120326195757/http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |archive-date=2012-03-26 }}</ref> and in Mongolia, it was personified as the White Old Man.<ref name=fong83/> Although the link was known in Tibet, with names such as ''Genpo karpo'' (''Rgan po dkar po'') or ''Genkar'' (''Rgan dkar'') "White Old Man", the symbolism was not popular. Instead, Canopus was more commonly named ''Karma Rishi སྐར་མ་རི་ཥི།'', derived from Indian mythology. Tibetans celebrated the star's heliacal rising with ritual bathing and associated it with morning dew.<ref name=baumann19/> ===Polynesia=== Bright stars were important to the ancient [[Polynesian culture|Polynesians]] for navigation between the many islands and atolls of the Pacific Ocean. Low on the horizon, they acted as stellar compasses to assist mariners in charting courses to particular destinations. Canopus served as the southern wingtip of a "Great Bird" constellation called ''Manu'', with Sirius as the body and [[Procyon]] the northern wingtip, which divided the Polynesian night sky into two hemispheres.<ref name="Holberg">{{cite book | last=Holberg | first=J.B. | title=Sirius: Brightest Diamond in the Night Sky | date=2007 | publisher=Praxis Publishing | location=Chichester, UK | isbn=978-0-387-48941-4 | pages=[https://archive.org/details/siriusbrightestd0000holb/page/25 25–26] | url=https://archive.org/details/siriusbrightestd0000holb/page/25 }}</ref> The [[Hawaiian people]] called Canopus ''Ke Alii-o-kona-i-ka-lewa'', "The chief of the southern expanse"; it was one of the stars used by [[Hawaiʻiloa]] and Ki when they traveled to the [[Southern Ocean]].{{sfn|Makemson|1941|p=198}} The [[Māori people]] of [[New Zealand|New Zealand/Aotearoa]] had several names for Canopus. ''[[Ariki]]'' ("High-born"), was known as a solitary star that appeared in the east, prompting people to weep and chant.{{sfn|Makemson|1941|p=201}} They also named it ''[[Atutahi]]'', ''Aotahi'' or ''Atuatahi'', "Stand Alone".<ref>p. 419, [https://books.google.com/books?id=p7dR2w1Wv2sC ''Mythology: Myths, Legends and Fantasies''], Janet Parker, Alice Mills, Julie Stanton, Durban, Struik Publishers, 2007.</ref> Its solitary nature indicates it is a ''[[Tapu (Polynesian culture)|tapu]]'' star, as ''tapu'' people are often solitary. Its appearance at the beginning of the ''Maruaroa'' season foretells the coming winter; light rays to the south indicate a cold wet winter, and to the north foretell a mild winter. Food was offered to the star on its appearance.<ref name="Best22">{{cite book|last=Best|first=Elsdon|title=Astronomical Knowledge of the Maori: Genuine and Empirical|publisher=Dominion Museum|location=Wellington, New Zealand|date=1922|pages=34–35|url=http://nzetc.victoria.ac.nz/tm/scholarly/tei-BesAstro-t1-body-d1-d6-d4.html}}</ref> This name has several mythologies attached to it. One story tells of how Atutahi was left outside the basket representing the [[Milky Way]] when [[Tāne]] wove it. Another related myth about the star says that Atutahi was the first-born child of [[Rangi and Papa|Rangi]], who refused to enter the Milky Way and so turned it sideways and rose before it. The same name is used for other stars and constellations throughout Polynesia.{{sfn|Makemson|1941|pp=200–202}} ''Kapae-poto'', "Short horizon", referred to it rarely setting as seen in New Zealand;{{sfn|Makemson|1941|p=217}} ''Kauanga'' ("Solitary") was the name for Canopus only when it was the last star visible before sunrise.{{sfn|Makemson|1941|p=218}} The people of the [[Society Islands]] had two names for Canopus, as did the [[Tuamotu]] people. The Society Islanders called Canopus ''Taurua-e-tupu-tai-nanu'', "Festivity-whence-comes-the-flux-of-the-sea", and ''Taurua-nui-o-te-hiti-apatoa'' "Great-festivity-of-the-border-of-the-south",{{sfn|Makemson|1941|p=259}} and the Tuamotu people called the star ''Te Tau-rari'' and ''Marere-te-tavahi'', the latter said to be the true name for the former, "He-who-stands-alone".{{sfn|Makemson|1941|p=229}} ===Africa=== In the [[Guanches|Guanche]] mythology of the island of [[Tenerife]] (Spain), the star Canopus was linked with the goddess [[Chaxiraxi]].<ref name="Rumeu">{{cite book|author=Antonio Rumeu de Armas|title=La conquista de Tenerife, 1494–1496|url=https://books.google.com/books?id=Ck4BAAAAMAAJ|year=1975|publisher=Aula de Cultura de Tenerife|isbn=9788450071078}}</ref> The [[Tswana people]] of [[Botswana]] knew Canopus as ''Naka''. Appearing late in winter skies, it heralded increasing winds and a time when trees lose their leaves. Stock owners knew it was time to put their sheep with rams.<ref>{{cite journal|last=Clegg|first=Andrew|date=1986|title=Some Aspects of Tswana Cosmology|journal=Botswana Notes and Records|volume=18|pages=33–37|jstor=40979758 }}</ref> In southern Africa, the Sotho, Tswana and Venda people called Canopus ''Naka'' or ''Nanga'', “the Horn Star”, while the Zulu and Swazi called it ''inKhwenkwezi'' "Brilliant star". It appears in the predawn sky in the third week of May. According to the Venda, the first person to see Canopus would blow a ''phalaphala'' horn from the top of a hill, getting a cow for a reward. The Sotho chiefs also awarded a cow, and ordered their medicine men to roll bone dice and read the fortune for the coming year.<ref name=snedegar95>{{cite journal |last1=Snedegar |first1=K.V. |title=Stars and seasons in Southern Africa |journal=Vistas in Astronomy |date=1995 |volume=39 |issue=4 |pages=529–38 |doi=10.1016/0083-6656(95)00008-9|bibcode=1995VA.....39..529S }}</ref> To the [[ǀXam language|ǀXam]]-speaking [[Bushmen]] of South Africa, Canopus and Sirius signalled the appearance of termites and flying ants. They also believed that stars had the power to cause death and misfortune, and they would pray to [[Sirius]] and Canopus in particular to impart good fortune or skill.<ref>{{cite journal| title="The Sky's Things", <nowiki>|</nowiki>xam Bushman 'Astrological Mythology' as recorded in the Bleek and Lloyd Manuscripts |last1=Hollman|first1=J. C.|journal=African Sky|volume= 11|page=8 |bibcode=2007AfrSk..11....8H|year = 2007 }}</ref> The [[ǃKung people]] of the [[Kalahari Desert]] in Botswana held Canopus and Capella to be the horns of ''tshxum'' (the Pleiades), the appearance of all three marking the end of the dry season and start of the rainy season.<ref>{{cite journal |last1=Marshall |first1=Lorna |title=Two Ju/ wa constellations |journal=Botswana Notes & Records |date=1975 |volume=7 |issue=1 |pages=153–159 | issn=0525-5090 |url=https://journals.co.za/docserver/fulltext/botnotes/7/1/548.pdf?expires=1590793041&id=id&accname=guest&checksum=3204085F9555AD9D083799E1F38E3AED}}</ref> ===Americas=== The [[Navajo]] observed the star and named it ''Maʼii Bizòʼ'', the “Coyote Star”. According to legend, Maʼii (Coyote) took part in the naming and placing of the star constellations during the creation of the universe. He placed Canopus directly south, naming it after himself.<ref name="Maryboy">Maryboy, Nancy D. (2004). ''A Guide to Navajo Astronomy.'' Indigenous Education Institute : Bluff, Utah.</ref> The [[Kalapalo]] people of [[Mato Grosso]] state in Brazil saw Canopus and [[Procyon]] as ''Kofongo'' "Duck", with [[Castor (star)|Castor]] and [[Pollux (star)|Pollux]] representing his hands. The asterism's appearance signified the coming of the rainy season and increase in [[manioc]], a food staple fed to guests at feasts.<ref name="basso87">{{cite book|last=Basso|first=Ellen B. |title=In Favor of Deceit: A Study of Tricksters in an Amazonian Society|publisher=University of Arizona Press|location=Tucson, Arizona|date=1987|page=[https://archive.org/details/infavorofdeceits0000bass/page/360 360]|isbn=0816510229|url=https://archive.org/details/infavorofdeceits0000bass|url-access=registration}}</ref> ===Australia=== Canopus is identified as the moiety ancestor ''Waa'' "Crow" to some [[Koori]] people in southeastern Australia.<ref>{{cite book|last=Mudrooroo|title=Aboriginal mythology: an A-Z spanning the history of aboriginal mythology from the earliest legends to the present day|publisher=HarperCollins|location=London|date=1994|page=27|isbn=1-85538-306-3}}</ref> The Boorong people of northwestern Victoria recalled that ''War'' (Canopus) was the brother of ''Warepil'' (Sirius), and that he brought fire from the heavens and introduced it to humanity. His wife was ''Collowgullouric War'' ([[Eta Carinae]]).<ref name=hamacher10>{{cite journal|last1=Hamacher|first1=Duane W. |last2=Frew|first2=David J. |date=2010|title= An Aboriginal Australian Record of the Great Eruption of Eta Carinae|journal=Journal of Astronomical History & Heritage |volume=13|issue=3|pages= 220–34|bibcode=2010JAHH...13..220H|arxiv = 1010.4610 }}</ref> The Pirt-Kopan-noot people of western Victoria tell of ''Waa'' "Crow" falling in love with a queen, ''Gneeanggar'' "Wedge-tailed Eagle" (Sirius) and her six attendants (the Pleiades). His advances spurned, he hears that the women are foraging for grubs and so transforms himself into a grub. When the women dig him out, he changes into a giant and carries her off.<ref>Mudroodoo, p. 55.</ref> The Kulin people know Canopus as ''Lo-an-tuka''.<ref name=hamacher10/> Objects in the sky are also associated with states of being for some tribes; the Wailwun of northern New South Wales know Canopus as ''Wumba'' "deaf", alongside Mars as ''Gumba'' "fat" and Venus as ''Ngindigindoer'' "you are laughing".<ref name="noctuary">{{cite book|last=Johnson|first=Diane|title=Night skies of aboriginal Australia: a noctuary|publisher=University of Sydney|location=Darlington, New South Wales|date=1998|page=[https://archive.org/details/nightskiesofabor0000john/page/84 84]|isbn=1-86451-356-X|url-access=registration|url=https://archive.org/details/nightskiesofabor0000john/page/84}}</ref> Tasmanian aboriginal lore holds that Canopus is ''Dromerdene'', the brother of ''Moinee''; the two fought and fell out of the sky, with ''Dromerdene'' falling into Louisa Bay in southwest Tasmania.<ref name="haynes2000">{{cite book|last=Haynes|first=Ros D.|title= Astronomy and the Dreaming: The Astronomy of the Aboriginal Australians. Astronomy Across Cultures: The History of Non-Western Astronomy|publisher=Kluwer Academic Publishers|date=2000|page=57|doi=10.1007/978-94-011-4179-6_3}}</ref> ===Legacy=== [[File:HMS Glory LOC ggbain.17135.jpg|thumb|right|[[Canopus-class battleship]] HMS Glory]] Canopus appears on the [[flag of Brazil]], symbolising the state of [[Goiás]].<ref>{{cite web |title=Astronomy of the Brazilian Flag |url=https://flagspot.net/flags/br_astro.html |publisher=FOTW Flags Of The World website }}</ref> Two U.S. Navy [[submarine tender]]s have been named after Canopus, the [[USS Canopus (AS-9)|first]] serving from 1922 to 1942 and the [[USS Canopus (AS-34)|second]] serving from 1965 to 1994. The [[Royal Navy]] built nine [[Canopus-class ship of the line|Canopus-class ships of the line]] in the early 19th century, and six {{Sclass|Canopus|battleship|1}}s which entered services between 1899 and 1902. There are at least two mountains named after the star: [[Mount Canopus]] in Antarctica; and Mount Canopus or Canopus Hill in [[Tasmania]], the location of the [[Canopus Hill Observatory|Canopus Hill astronomical observatory]]. {{clear}} c86b7d744cb72178d88d269c62077bd1a55baad5 Main Page 0 1 351 86 2022-09-25T12:56:57Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ Welcome to {{SITENAME}}! AstroBase is an online encyclopaedia for astronomy and a wiki. Currently in development. ===Quick List=== [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] ===Astronomy Database Portal=== [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 52ca8de1d94227ffff184c7666ee73bc5ec5288f 352 351 2022-09-26T17:50:31Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ Welcome to {{SITENAME}}! Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . {{SITENAME}} is a project to create a wiki dedicated to astronomy. ==Quick List== [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] ==Astronomy Database Portal== [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] a9a1dee48edbee14e252091c7ac25dc56ac5cd5a 353 352 2022-09-26T17:53:23Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!''' Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . {{SITENAME}} is a project to create a wiki dedicated to astronomy. '''Quick List''' [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal''' [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 70f13f6c6343f47d8f3a2f1065b77da20aef1801 Main Page 0 1 354 353 2022-09-26T18:05:17Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . {{SITENAME}} is a project to create a wiki dedicated to astronomy. '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] {{search box |root= / |search-break=<yes|no> |search-width=number |search-button-label=text }} 040e139986fc09d89a2baa4b82ad1afe5434a5a3 355 354 2022-09-26T18:05:38Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . {{SITENAME}} is a project to create a wiki dedicated to astronomy. '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 4322d04b76ad693af8433b43daf8230add9d495f 356 355 2022-09-26T18:07:01Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It tries to explains the origin and end of Universe '''{{SITENAME}}''' is a project to create a wiki dedicated to astronomy. '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 0f0ddf380ea7452c90c0a6215e2ca990ade5e8b3 357 356 2022-10-05T06:59:09Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It uses mathematics, physics, and chemistry in order to explain their origin and evolution. '''{{SITENAME}}''' is a wiki dedicated to astronomy. Note: Project is in Development '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] aeebae5c26bc6cf2b25db12ed6d0b249762f01e8 358 357 2022-10-05T07:01:22Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It uses mathematics, physics, and chemistry in order to explain their origin and evolution. '''{{SITENAME}}''' is a wiki dedicated to astronomy. <br> {{Box-round|title=Note|Astrobase is in development}} '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 945d32b551627dd2c7ebf5029bc740a1824b5b19 359 358 2022-10-05T07:03:58Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It uses mathematics, physics, and chemistry in order to explain their origin and evolution. '''{{SITENAME}}''' is a wiki dedicated to astronomy. <br> '''Note : Wiki is in development''' '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] ce22d629555437f3f99f5e9560d7b23fc968cdff 364 359 2023-02-22T10:03:47Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It uses mathematics, physics, and chemistry in order to explain their origin and evolution. '''{{SITENAME}}''' is a wiki dedicated to astronomy and will also include Pages about battleships and tanks. <br> '''Note : Wiki is in development''' '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] 4aa8c5a28c7e5204cd7bd6bc5b68b3d81cda0b04 370 364 2023-06-04T06:38:17Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} __FORCETOC__ '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It uses mathematics, physics, and chemistry in order to explain their origin and evolution. '''{{SITENAME}}''' is a wiki dedicated to astronomy . <br> '''Note : Wiki is in development''' '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] a6ff609cbbbb5fcf41845c84aae87db9e82bfd3a 381 370 2023-07-07T05:10:55Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase Home }} '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It uses mathematics, physics, and chemistry in order to explain their origin and evolution. '''{{SITENAME}}''' is a wiki dedicated to astronomy . <br> '''Note : Wiki is in development''' '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] [[File:Logospaceman.png|alt=Logo|thumb]] [[Category:Main]] __NOEDITSECTION__ __INDEX__ dc3d7c976652c1cfdab7de03f2a45ef2761e5b33 396 381 2023-07-07T17:53:46Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase}} '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It uses mathematics, physics, and chemistry in order to explain their origin and evolution. '''{{SITENAME}}''' is a wiki dedicated to astronomy . <br> '''Note : Wiki is in development''' '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] <!-- Disclaimer: AI generated text are also being used , so if you find any mistake kindly reach The administrator --> [[File:Logospaceman.png|alt=Logo|thumb]] [[Category:Main]] __NOEDITSECTION__ __INDEX__ __FORCETOC__ __NONEWSECTIONLINK__ f4d7045dcaf5417b5f9b0622c7edd8bbfa5b5104 Active Galactic Nucleus 0 167 360 2022-10-09T11:26:15Z SpaceMan 2 Created page with "===Definition=== active galactic nucleus (AGN) The central region of a distant active galaxy that appears to be a point-like source of intense X-ray or gamma ray emissions. Astrophysicists specu- late that the AGN is caused by the presence of a centrally located, supermassive black hole accreting nearby matter." wikitext text/x-wiki ===Definition=== active galactic nucleus (AGN) The central region of a distant active galaxy that appears to be a point-like source of intense X-ray or gamma ray emissions. Astrophysicists specu- late that the AGN is caused by the presence of a centrally located, supermassive black hole accreting nearby matter. 94a587cb175198d4bfb146195051cfe3b5340345 361 360 2022-10-09T11:27:03Z SpaceMan 2 /* Definition */ wikitext text/x-wiki ==Definition== Active galactic nucleus (AGN) The central region of a distant active galaxy that appears to be a point-like source of intense X-ray or gamma ray emissions. Astrophysicists specu- late that the AGN is caused by the presence of a centrally located, supermassive black hole accreting nearby matter. b64e23dcecf0c0d078ab78f119f16a823960ce1a SpaceMan:About 4 168 362 2023-02-21T17:17:11Z SpaceMan 2 About wikitext text/x-wiki Welcome to our astronomy website! Here, you can explore the vast wonders of the universe and satisfy your curiosity about everything that lies beyond our planet. Our website provides a comprehensive and user-friendly platform for anyone who is interested in astronomy, from beginners to advanced stargazers. NOTE - THIS WEBSITE IS STILL IN DEVELOPMENT AND NEEDS MORE CONTENT. AND YOU ARE WELCOME TO CONTRIBUTE HERE, THANK YOU 7d46a726aa15c157e73d04ffd066827d8f6f54c9 363 362 2023-02-21T17:18:27Z SpaceMan 2 Protected "[[SpaceMan:About]]" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) wikitext text/x-wiki Welcome to our astronomy website! Here, you can explore the vast wonders of the universe and satisfy your curiosity about everything that lies beyond our planet. Our website provides a comprehensive and user-friendly platform for anyone who is interested in astronomy, from beginners to advanced stargazers. NOTE - THIS WEBSITE IS STILL IN DEVELOPMENT AND NEEDS MORE CONTENT. AND YOU ARE WELCOME TO CONTRIBUTE HERE, THANK YOU 7d46a726aa15c157e73d04ffd066827d8f6f54c9 Nebulae 0 169 365 2023-03-06T15:23:41Z SpaceMan 2 Created page with "**Definition** A nebula is a vast cloud of interstellar gas and dust within a galaxy, typically illuminated by starlight or other radiation sources. Nebulae come in a variety of shapes and sizes, from small, dense regions of gas and dust to massive, diffuse clouds that stretch across thousands of light-years. Some nebulae are the birthplace of new stars, while others are the remnants of stars that have died. Nebulae can be observed in different wavelengths, including vi..." wikitext text/x-wiki **Definition** A nebula is a vast cloud of interstellar gas and dust within a galaxy, typically illuminated by starlight or other radiation sources. Nebulae come in a variety of shapes and sizes, from small, dense regions of gas and dust to massive, diffuse clouds that stretch across thousands of light-years. Some nebulae are the birthplace of new stars, while others are the remnants of stars that have died. Nebulae can be observed in different wavelengths, including visible light, ultraviolet, and infrared, which allows astronomers to study their properties and evolution. 115564120c4cb428695a290cbf6c5aae6b427823 366 365 2023-03-06T15:25:52Z SpaceMan 2 wikitext text/x-wiki #'''Definition''' A nebula is a vast cloud of interstellar gas and dust within a galaxy, typically illuminated by starlight or other radiation sources. Nebulae come in a variety of shapes and sizes, from small, dense regions of gas and dust to massive, diffuse clouds that stretch across thousands of light-years. Some nebulae are the birthplace of new stars, while others are the remnants of stars that have died. Nebulae can be observed in different wavelengths, including visible light, ultraviolet, and infrared, which allows astronomers to study their properties and evolution. 13abaa5524062a15778039cbcb96b59def7c6e89 367 366 2023-03-06T15:37:21Z SpaceMan 2 wikitext text/x-wiki #'''Definition''' A nebula is a vast cloud of interstellar gas and dust within a galaxy, typically illuminated by starlight or other radiation sources. Nebulae come in a variety of shapes and sizes, from small, dense regions of gas and dust to massive, diffuse clouds that stretch across thousands of light-years. Some nebulae are the birthplace of new [[star]], while others are the remnants of stars that have died. Nebulae can be observed in different wavelengths, including visible light, ultraviolet, and infrared, which allows astronomers to study their properties and evolution. #'''Types''' Emission Nebulae: These are brightly glowing clouds of ionized gas, typically reddish or pinkish in color, that are often associated with young, hot stars. Examples include the famous Orion Nebula and the Lagoon Nebula. Reflection Nebulae: These are clouds of dust that reflect the light of nearby stars, appearing blue in color. The most well-known example is the Pleiades [[star cluster]]. Planetary Nebulae: These are shells of gas and dust ejected by a dying star in its final stages of life. Despite the name, they have nothing to do with planets. Examples include the Ring Nebula and the Helix Nebula. Dark Nebulae: These are dense clouds of gas and dust that obscure the light of background stars, appearing as dark patches against the [[Milky Way]]. Examples include the Horsehead Nebula and the Pipe Nebula. Supernova Remnants: These are the expanding shells of gas and dust left behind by a supernova explosion. Examples include the Crab Nebula and the Veil Nebula. Molecular Clouds: These are the largest and most massive of all nebulae, consisting of cold, dense gas and dust that is the birthplace of new stars. Examples include the Taurus Molecular Cloud and the Orion Molecular Cloud. b1e94453fbb7ba1a072ae02c954bccabe7c890a3 368 367 2023-03-06T15:38:19Z SpaceMan 2 wikitext text/x-wiki #'''Definition''' A nebula is a vast cloud of interstellar gas and dust within a galaxy, typically illuminated by starlight or other radiation sources. Nebulae come in a variety of shapes and sizes, from small, dense regions of gas and dust to massive, diffuse clouds that stretch across thousands of light-years. Some nebulae are the birthplace of new [[star]], while others are the remnants of stars that have died. Nebulae can be observed in different wavelengths, including visible light, ultraviolet, and infrared, which allows astronomers to study their properties and evolution. ===Types=== Emission Nebulae: These are brightly glowing clouds of ionized gas, typically reddish or pinkish in color, that are often associated with young, hot stars. Examples include the famous Orion Nebula and the Lagoon Nebula. Reflection Nebulae: These are clouds of dust that reflect the light of nearby stars, appearing blue in color. The most well-known example is the Pleiades [[star cluster]]. Planetary Nebulae: These are shells of gas and dust ejected by a dying star in its final stages of life. Despite the name, they have nothing to do with planets. Examples include the Ring Nebula and the Helix Nebula. Dark Nebulae: These are dense clouds of gas and dust that obscure the light of background stars, appearing as dark patches against the [[Milky Way]]. Examples include the Horsehead Nebula and the Pipe Nebula. Supernova Remnants: These are the expanding shells of gas and dust left behind by a supernova explosion. Examples include the Crab Nebula and the Veil Nebula. Molecular Clouds: These are the largest and most massive of all nebulae, consisting of cold, dense gas and dust that is the birthplace of new stars. Examples include the Taurus Molecular Cloud and the Orion Molecular Cloud. db052bd3eb42b473129b8e050ef0ea7f854f5266 Milky Way 0 170 369 2023-06-04T06:35:05Z SpaceMan 2 Milky way wikitext text/x-wiki The Milky Way is a barred spiral galaxy that is home to our own [solar system] and numerous other stars. It is estimated to contain between 100 and 400 billion stars, making it one of the largest galaxies in the known universe. [The Milky Way] is approximately 100,000 light-years in diameter and is thought to be about 13.5 billion years old. The [Milky Way] is named after the band of light that is visible in the night sky, which is caused by the concentration of stars and other celestial objects in the galactic plane. The Milky Way is located in the [Local Group], a cluster of more than 50 galaxies that includes the [Andromeda Galaxy] and the Triangulum Galaxy. The Milky Way and the Andromeda Galaxy are the two largest members of the Local Group, and are expected to collide in about 4.5 billion years. The Milky Way has a central bar-shaped structure surrounded by four major spiral arms, and several smaller arms and spurs. The central bar is thought to be about 27,000 light-years long and 3,000 light-years wide. The spiral arms regions of enhanced star formation and are named the [Norma Arm], the Scutum-Centaurus Arm, the [Sagittarius Arm], and the [Perseus] Arm. The Milky Way also contains a supermassive black hole at its center, known as Sagittarius A*. This black hole has a mass of about 4.1 million times that of the Sun and is surrounded by a disk of gas and dust. The black hole is currently in a quiescent state, but is thought to have been more active in the past. The study of the Milky Way and its structure is an ongoing field of research, with astronomers using a variety of techniques and instruments to explore the galaxy. These include telescopes that observe in the visible, infrared, and radio wavelengths, as well as spacecraft that have been sent to study the galaxy's structure and composition. By studying the Milky Way, astronomers hope to gain a better understanding of the formation and evolution of galaxies, as well as the formation and evolution of our own solar system. dd1a692bc931f7f86c2a64efafd13a60ecb2caf8 403 369 2023-07-13T03:19:56Z SpaceMan 2 wikitext text/x-wiki [[File:ESO - Milky Way.jpg|alt=Milky way|center|frameless|Milky Way]] The Milky Way is a barred spiral galaxy that is home to our own [solar system] and numerous other stars. It is estimated to contain between 100 and 400 billion stars, making it one of the largest galaxies in the known universe. [The Milky Way] is approximately 100,000 light-years in diameter and is thought to be about 13.5 billion years old. The [Milky Way] is named after the band of light that is visible in the night sky, which is caused by the concentration of stars and other celestial objects in the galactic plane. The Milky Way is located in the [Local Group], a cluster of more than 50 galaxies that includes the [Andromeda Galaxy] and the Triangulum Galaxy. The Milky Way and the Andromeda Galaxy are the two largest members of the Local Group, and are expected to collide in about 4.5 billion years. The Milky Way has a central bar-shaped structure surrounded by four major spiral arms, and several smaller arms and spurs. The central bar is thought to be about 27,000 light-years long and 3,000 light-years wide. The spiral arms regions of enhanced star formation and are named the [Norma Arm], the Scutum-Centaurus Arm, the [Sagittarius Arm], and the [Perseus] Arm. The Milky Way also contains a supermassive black hole at its center, known as Sagittarius A*. This black hole has a mass of about 4.1 million times that of the Sun and is surrounded by a disk of gas and dust. The black hole is currently in a quiescent state, but is thought to have been more active in the past. The study of the Milky Way and its structure is an ongoing field of research, with astronomers using a variety of techniques and instruments to explore the galaxy. These include telescopes that observe in the visible, infrared, and radio wavelengths, as well as spacecraft that have been sent to study the galaxy's structure and composition. By studying the Milky Way, astronomers hope to gain a better understanding of the formation and evolution of galaxies, as well as the formation and evolution of our own solar system. [[Category:Astronomy]] {{DEFAULTSORT:MilkyWay}} __FORCETOC__ __INDEX__ fbf0e4b8eafd99ac96792fa93e17a79d46009587 Sun 0 171 371 2023-06-08T07:22:19Z SpaceMan 2 Created page with "{| class="wikitable" |+Data |Name |Sun , Sol |- |Size |Apple |- |Distance from Earth |1.496×108 km , 1AU |- |Mass |1.9885×1030 kg |} The sun is a star located at the center of the solar system and is the closest star to [[Earth]]. It is a nearly perfect sphere of hot plasma, with internal convective that generates a magnetic field. It has a diameter of approximately 1.39 million kilometers (865,000 miles), which is about 109 times the diameter of Earth. Its mass is abo..." wikitext text/x-wiki {| class="wikitable" |+Data |Name |Sun , Sol |- |Size |Apple |- |Distance from Earth |1.496×108 km , 1AU |- |Mass |1.9885×1030 kg |} The sun is a star located at the center of the solar system and is the closest star to [[Earth]]. It is a nearly perfect sphere of hot plasma, with internal convective that generates a magnetic field. It has a diameter of approximately 1.39 million kilometers (865,000 miles), which is about 109 times the diameter of Earth. Its mass is about 330,000 times that of Earth, making up about 99.86% of the total mass of the [[solar system]]. The sun's [[energy]] is generated by [[nuclear fusion]] in its [[core]], where hydrogen is converted into helium. This process releases an enormous amount of energy in the form of light and heat, which is radiated outwards in all directions. The energy generated by the sun is responsible for sustaining life on Earth and driving the planet's climate and weather patterns. The sun has a complex magnetic field, which can create [[sunspots]], [[solar flares]], and [[coronal mass ejections]]. These events can have a significant impact on Earth's environment, causing disruptions in satellite and telecommunications systems, power grids , and even posing a risk to [[astronauts]] in [[space]]. The sun is also responsible for creating the solar wind, a stream of charged particles that flows outwards from the sun and permeates the entire solar system. This wind plays a crucial role in shaping the planets' magnetospheres and protecting them from harmful [[cosmic radiation]]. The sun is estimated to be about 4.6 billion years old and is expected to continue to shine for another 5 billion years or so before running out of fuel and eventually becoming a white dwarf. Its importance to life on Earth and its influence on the wider universe make it one of the most studied objects in [[astronomy]] and [[astrophysics]]. 2453664ba07c3ddb7af72ac35070b4d48b0ce04f 399 371 2023-07-09T09:44:27Z SpaceMan 2 wikitext text/x-wiki {| class="wikitable" |+Data |Name |Sun , Sol |- |Galactic Period |(2.25-2.50)*10<sup>8</sup> yr |- |Distance from Earth |1.496×10<sup>8</sup> km , 1AU |- |Mass |1.9885×10<sup>30</sup> kg |} The sun is a star located at the center of the solar system and is the closest star to [[Earth]]. It is a nearly perfect sphere of hot plasma, with internal convective that generates a magnetic field. It has a diameter of approximately 1.39 million kilometers (865,000 miles), which is about 109 times the diameter of Earth. Its mass is about 330,000 times that of Earth, making up about 99.86% of the total mass of the [[solar system]]. The sun's [[energy]] is generated by [[nuclear fusion]] in its [[core]], where hydrogen is converted into helium. This process releases an enormous amount of energy in the form of light and heat, which is radiated outwards in all directions. The energy generated by the sun is responsible for sustaining life on Earth and driving the planet's climate and weather patterns. The sun has a complex magnetic field, which can create [[sunspots]], [[solar flares]], and [[coronal mass ejections]]. These events can have a significant impact on Earth's environment, causing disruptions in satellite and telecommunications systems, power grids , and even posing a risk to [[astronauts]] in [[space]]. The sun is also responsible for creating the solar wind, a stream of charged particles that flows outwards from the sun and permeates the entire solar system. This wind plays a crucial role in shaping the planets' magnetospheres and protecting them from harmful [[cosmic radiation]]. The sun is estimated to be about 4.6 billion years old and is expected to continue to shine for another 5 billion years or so before running out of fuel and eventually becoming a white dwarf. Its importance to life on Earth and its influence on the wider universe make it one of the most studied objects in [[astronomy]] and [[astrophysics]]. 552fd79f4263be376d5e07803d30d0f2f256d9a9 Bohr Atomic Model 0 172 372 2023-07-07T04:42:22Z SpaceMan 2 Created page with "# Bohr Atomic Model ## Definition '''Given by''' - Neil Bohr To overcome the drawback of [[Rutherford model]], a new model of atom was introduced based on ''atomic spectra'' and is known as Bohr model of atom. ## Postulates Quantization of angular momentum for the electron moving in any orbit. Quantization** is defined as any quantity whose value of magnitude is integral multiple of any constant value is called is quantization. Quantization of angular momentum sta..." wikitext text/x-wiki # Bohr Atomic Model ## Definition '''Given by''' - Neil Bohr To overcome the drawback of [[Rutherford model]], a new model of atom was introduced based on ''atomic spectra'' and is known as Bohr model of atom. ## Postulates Quantization of angular momentum for the electron moving in any orbit. Quantization** is defined as any quantity whose value of magnitude is integral multiple of any constant value is called is quantization. Quantization of angular momentum states that for any electron occupying any orbit inside atom is always quantized and is integral multiple of a constant ** h/2π** where , h - Planck's constant (6.626 * 10<sup>-34</sup> joules second). Angular Momentum: mvr = nh/2π Where '''m''' denotes ''mass'' '''v''' denotes ''velocity'' and '''r''' denotes ''radius of orbit'' in which electron is present. --- #### Quantization of Energy Inside atom there are infinite number of orbit each having a fixed constant value of energy but the energy of all orbit are quite different from each other. As we move away from the nucleus energy of orbit goes on increasing. The energy of it's infinite orbit is maximum possible and is equal to zero this concludes that energy of electron in any orbit inside atom has negative sign with its magnitude. An atom inside atom occupies that orbit whose energy is exactly equal to the energy of electron. An electron occupying its native orbit revolve around the nucleus continuously without absorbing or an emitting any radiation all such orbits are called stationary orbit. Whenever of a finite frequency radiation provides a finite amount of energy to such an electron it jumps into a higher energy orbit and continues its motion in higher energy orbit called as excited states till supply of energy is maintained. As soon as supply of energy is stopped electron comes back to its original native state by emitting same frequency radiation. ## Drawbacks It does not explain Zeeman's and Stark's effect. '''Zeeman Effect:''' When spectral line is placed in magnetic field spectral line split up into sublines. '''Stark Effect:''' if splitting of spectral lines take place in electric field then it is known as Stark effect. Electron shows phenomena of diffraction and interference which indicates that there is wave nature in electron but there is no explanation of wave nature for electron in his model. Does not explain the spectrum of multi electron system. Experimental evidences shows that orbits are composed of suborbits / subshell but in Bohr's model there is no such concept of subshell / suborbit. Does not explain the spectrum of multielectron system. 29844ab095c6965d2dc51a338a932abba0a53b82 373 372 2023-07-07T04:49:52Z SpaceMan 2 Editing wikitext text/x-wiki == Bohr Atomic Model == === Definition: === ## '''Given by''' - Neil Bohr To overcome the drawback of [[Rutherford model]], a new model of atom was introduced based on ''atomic spectra'' and is known as Bohr model of atom. ==== Postulates: ==== ## Postulates Quantization of angular momentum for the electron moving in any orbit. Quantization** is defined as any quantity whose value of magnitude is integral multiple of any constant value is called is quantization. Quantization of angular momentum states that for any electron occupying any orbit inside atom is always quantized and is integral multiple of a constant <math>h/2π</math> where , h - Planck's constant (6.626 * 10<sup>-34</sup> joules second). Angular Momentum: mvr = nh/2π Where '''m''' denotes ''mass'' '''v''' denotes ''velocity'' and '''r''' denotes ''radius of orbit'' in which electron is present. --- # I Inside atom there are infinite number of orbit each having a fixed constant value of energy but the energy of all orbit are quite different from each other. As we move away from the nucleus energy of orbit goes on increasing. The energy of it's infinite orbit is maximum possible and is equal to zero this concludes that energy of electron in any orbit inside atom has negative sign with its magnitude. An atom inside atom occupies that orbit whose energy is exactly equal to the energy of electron. An electron occupying its native orbit revolve around the nucleus continuously without absorbing or an emitting any radiation all such orbits are called stationary orbit. Whenever of a finite frequency radiation provides a finite amount of energy to such an electron it jumps into a higher energy orbit and continues its motion in higher energy orbit called as excited states till supply of energy is maintained. As soon as supply of energy is stopped electron comes back to its original native state by emitting same frequency radiation. # # ==== Drawbacks: ==== It does not explain Zeeman's and Stark's effect. '''Zeeman Effect:''' When spectral line is placed in magnetic field spectral line split up into sublines. '''Stark Effect:''' if splitting of spectral lines take place in electric field then it is known as Stark effect. Electron shows phenomena of diffraction and interference which indicates that there is wave nature in electron but there is no explanation of wave nature for electron in his model. Does not explain the spectrum of multi electron system. Experimental evidences shows that orbits are composed of suborbits / subshell but in Bohr's model there is no such concept of subshell / suborbit. Does not explain the spectrum of multielectron system. [[Category:Chemistry]] __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 9cb501d675b45901fc6e92970d5564defd168d1e 374 373 2023-07-07T04:55:35Z SpaceMan 2 wikitext text/x-wiki Bohot Atomic Model === Definition: === '''Given by''' - Neil Bohr To overcome the drawback of [[Rutherford model]], a new model of atom was introduced based on ''atomic spectra'' and is known as Bohr model of atom. ==== Postulates: ==== Quantization of angular momentum for the electron moving in any orbit. Quantization** is defined as any quantity whose value of magnitude is integral multiple of any constant value is called is quantization. Quantization of angular momentum states that for any electron occupying any orbit inside atom is always quantized and is integral multiple of a constant <math>h/2π</math> where , h - Planck's constant (6.626 * 10<sup>-34</sup> joules second). Angular Momentum: mvr = nh/2π Where '''m''' denotes ''mass'' '''v''' denotes ''velocity'' and '''r''' denotes ''radius of orbit'' in which electron is present. Inside atom there are infinite number of orbit each having a fixed constant value of energy but the energy of all orbit are quite different from each other. As we move away from the nucleus energy of orbit goes on increasing. The energy of it's infinite orbit is maximum possible and is equal to zero this concludes that energy of electron in any orbit inside atom has negative sign with its magnitude. An atom inside atom occupies that orbit whose energy is exactly equal to the energy of electron. An electron occupying its native orbit revolve around the nucleus continuously without absorbing or an emitting any radiation all such orbits are called stationary orbit. Whenever of a finite frequency radiation provides a finite amount of energy to such an electron it jumps into a higher energy orbit and continues its motion in higher energy orbit called as excited states till supply of energy is maintained. As soon as supply of energy is stopped electron comes back to its original native state by emitting same frequency radiation. ==== Drawbacks: ==== It does not explain Zeeman's and Stark's effect. '''Zeeman Effect:''' When spectral line is placed in magnetic field spectral line split up into sublines. '''Stark Effect:''' if splitting of spectral lines take place in electric field then it is known as Stark effect. Electron shows phenomena of diffraction and interference which indicates that there is wave nature in electron but there is no explanation of wave nature for electron in his model. Does not explain the spectrum of multi electron system. Experimental evidences shows that orbits are composed of suborbits / subshell but in Bohr's model there is no such concept of subshell / suborbit. Does not explain the spectrum of multielectron system. [[Category:Chemistry]] __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 9ec90be3ad3a791f1a159a93ad6e9ca9b0ea14b9 375 374 2023-07-07T04:55:57Z SpaceMan 2 wikitext text/x-wiki === Definition: === '''Given by''' - Neil Bohr To overcome the drawback of [[Rutherford model]], a new model of atom was introduced based on ''atomic spectra'' and is known as Bohr model of atom. ==== Postulates: ==== Quantization of angular momentum for the electron moving in any orbit. Quantization** is defined as any quantity whose value of magnitude is integral multiple of any constant value is called is quantization. Quantization of angular momentum states that for any electron occupying any orbit inside atom is always quantized and is integral multiple of a constant <math>h/2π</math> where , h - Planck's constant (6.626 * 10<sup>-34</sup> joules second). Angular Momentum: mvr = nh/2π Where '''m''' denotes ''mass'' '''v''' denotes ''velocity'' and '''r''' denotes ''radius of orbit'' in which electron is present. Inside atom there are infinite number of orbit each having a fixed constant value of energy but the energy of all orbit are quite different from each other. As we move away from the nucleus energy of orbit goes on increasing. The energy of it's infinite orbit is maximum possible and is equal to zero this concludes that energy of electron in any orbit inside atom has negative sign with its magnitude. An atom inside atom occupies that orbit whose energy is exactly equal to the energy of electron. An electron occupying its native orbit revolve around the nucleus continuously without absorbing or an emitting any radiation all such orbits are called stationary orbit. Whenever of a finite frequency radiation provides a finite amount of energy to such an electron it jumps into a higher energy orbit and continues its motion in higher energy orbit called as excited states till supply of energy is maintained. As soon as supply of energy is stopped electron comes back to its original native state by emitting same frequency radiation. ==== Drawbacks: ==== It does not explain Zeeman's and Stark's effect. '''Zeeman Effect:''' When spectral line is placed in magnetic field spectral line split up into sublines. '''Stark Effect:''' if splitting of spectral lines take place in electric field then it is known as Stark effect. Electron shows phenomena of diffraction and interference which indicates that there is wave nature in electron but there is no explanation of wave nature for electron in his model. Does not explain the spectrum of multi electron system. Experimental evidences shows that orbits are composed of suborbits / subshell but in Bohr's model there is no such concept of subshell / suborbit. Does not explain the spectrum of multielectron system. [[Category:Chemistry]] __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ c71781ea3859d5cb0f61a5a9f50471d122eef694 376 375 2023-07-07T04:58:35Z SpaceMan 2 wikitext text/x-wiki === Definition: === '''Given by''' - Neil Bohr To overcome the drawback of [[Rutherford model]], a new model of atom was introduced based on ''atomic spectra'' and is known as Bohr model of atom. ==== Postulates: ==== Quantization of angular momentum for the electron moving in any orbit. '''Quantization''' is defined as any quantity whose value of magnitude is integral multiple of any constant value is called is quantization. '''Quantization of angular momentum''' states that for any electron occupying any orbit inside atom is always quantized and is integral multiple of a constant <math>h/2π</math> where , h - Planck's constant (6.626 * 10<sup>-34</sup> joules second). '''Angular Momentum:''' mvr = nh/2π Where '''m''' denotes ''mass'' '''v''' denotes ''velocity'' and '''r''' denotes ''radius of orbit'' in which electron is present. Inside atom there are infinite number of orbit each having a fixed constant value of energy but the energy of all orbit are quite different from each other. As we move away from the nucleus energy of orbit goes on increasing. The energy of it's infinite orbit is maximum possible and is equal to zero this concludes that energy of electron in any orbit inside atom has negative sign with its magnitude. An atom inside atom occupies that orbit whose energy is exactly equal to the energy of electron. An electron occupying its native orbit revolve around the nucleus continuously without absorbing or an emitting any radiation all such orbits are called stationary orbit. Whenever of a finite frequency radiation provides a finite amount of energy to such an electron it jumps into a higher energy orbit and continues its motion in higher energy orbit called as excited states till supply of energy is maintained. As soon as supply of energy is stopped electron comes back to its original native state by emitting same frequency radiation. ==== Drawbacks: ==== It does not explain Zeeman's and Stark's effect. '''Zeeman Effect:''' When spectral line is placed in magnetic field spectral line split up into sublines. '''Stark Effect:''' if splitting of spectral lines take place in electric field then it is known as Stark effect. Electron shows phenomena of diffraction and interference which indicates that there is wave nature in electron but there is no explanation of wave nature for electron in his model. Does not explain the spectrum of multi electron system. Experimental evidences shows that orbits are composed of suborbits / subshell but in Bohr's model there is no such concept of subshell / suborbit. Does not explain the spectrum of multielectron system. [[Category:Chemistry]] __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 4a0403334bba64ecc2a73327aaf7187b88689fef 377 376 2023-07-07T05:02:13Z SpaceMan 2 wikitext text/x-wiki === Definition: === '''Given by''' - Neil Bohr To overcome the drawback of [[Rutherford model]], a new model of atom was introduced based on ''atomic spectra'' and is known as Bohr model of atom. ==== Postulates: ==== Quantization of angular momentum for the electron moving in any orbit. '''Quantization''' is defined as any quantity whose value of magnitude is integral multiple of any constant value is called is quantization. '''Quantization of angular momentum''' states that for any electron occupying any orbit inside atom is always quantized and is integral multiple of a constant <math>h/2π</math> where , h - Planck's constant (6.626 * 10<sup>-34</sup> joules second). '''Angular Momentum:''' mvr = nh/2π Where '''m''' denotes ''mass'' '''v''' denotes ''velocity'' and '''r''' denotes ''radius of orbit'' in which electron is present. Inside atom there are infinite number of orbit each having a fixed constant value of energy but the energy of all orbit are quite different from each other. As we move away from the nucleus energy of orbit goes on increasing. The energy of it's infinite orbit is maximum possible and is equal to zero this concludes that energy of electron in any orbit inside atom has negative sign with its magnitude. An atom inside atom occupies that orbit whose energy is exactly equal to the energy of electron. An electron occupying its native orbit revolve around the nucleus continuously without absorbing or an emitting any radiation all such orbits are called stationary orbit. Whenever of a finite frequency radiation provides a finite amount of energy to such an electron it jumps into a higher energy orbit and continues its motion in higher energy orbit called as excited states till supply of energy is maintained. As soon as supply of energy is stopped electron comes back to its original native state by emitting same frequency radiation. ==== Drawbacks: ==== It does not explain Zeeman's and Stark's effect. '''Zeeman Effect:''' When spectral line is placed in magnetic field spectral line split up into sublines. '''Stark Effect:''' if splitting of spectral lines take place in electric field then it is known as Stark effect. Electron shows phenomena of diffraction and interference which indicates that there is wave nature in electron but there is no explanation of wave nature for electron in his model. Does not explain the spectrum of multi electron system. Experimental evidences shows that orbits are composed of suborbits / subshell but in Bohr's model there is no such concept of subshell / suborbit. Does not explain the spectrum of multielectron system. <ref>https://en.m.wikipedia.org/wiki/Bohr_model</ref> [[Category:Chemistry]] __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 17ff30a19c81eae5ad5adb8e3f92897d972693d0 379 377 2023-07-07T05:05:38Z SpaceMan 2 wikitext text/x-wiki === Definition: === '''Given by''' - Neil Bohr To overcome the drawback of [[Rutherford model]], a new model of atom was introduced based on ''atomic spectra'' and is known as Bohr model of atom. [[File:Bohr atom model.svg.png|thumb|Bohr model ]] ==== Postulates: ==== Quantization of angular momentum for the electron moving in any orbit. '''Quantization''' is defined as any quantity whose value of magnitude is integral multiple of any constant value is called is quantization. '''Quantization of angular momentum''' states that for any electron occupying any orbit inside atom is always quantized and is integral multiple of a constant <math>h/2π</math> where , h - Planck's constant (6.626 * 10<sup>-34</sup> joules second). '''Angular Momentum:''' mvr = nh/2π Where '''m''' denotes ''mass'' '''v''' denotes ''velocity'' and '''r''' denotes ''radius of orbit'' in which electron is present. Inside atom there are infinite number of orbit each having a fixed constant value of energy but the energy of all orbit are quite different from each other. As we move away from the nucleus energy of orbit goes on increasing. The energy of it's infinite orbit is maximum possible and is equal to zero this concludes that energy of electron in any orbit inside atom has negative sign with its magnitude. An atom inside atom occupies that orbit whose energy is exactly equal to the energy of electron. An electron occupying its native orbit revolve around the nucleus continuously without absorbing or an emitting any radiation all such orbits are called stationary orbit. Whenever of a finite frequency radiation provides a finite amount of energy to such an electron it jumps into a higher energy orbit and continues its motion in higher energy orbit called as excited states till supply of energy is maintained. As soon as supply of energy is stopped electron comes back to its original native state by emitting same frequency radiation. ==== Drawbacks: ==== It does not explain Zeeman's and Stark's effect. '''Zeeman Effect:''' When spectral line is placed in magnetic field spectral line split up into sublines. '''Stark Effect:''' if splitting of spectral lines take place in electric field then it is known as Stark effect. Electron shows phenomena of diffraction and interference which indicates that there is wave nature in electron but there is no explanation of wave nature for electron in his model. Does not explain the spectrum of multi electron system. Experimental evidences shows that orbits are composed of suborbits / subshell but in Bohr's model there is no such concept of subshell / suborbit. Does not explain the spectrum of multielectron system. <ref>https://en.m.wikipedia.org/wiki/Bohr_model</ref> [[Category:Chemistry]] __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 198abf48532cfcda880e78ab32ee2bbdadbdd87c File:Bohr atom model.svg.png 6 173 378 2023-07-07T05:04:29Z SpaceMan 2 wikitext text/x-wiki Bohr model of atom 907237496d252668981efecc93d326ccd63981e0 Category:Chemistry 14 174 380 2023-07-07T05:07:04Z SpaceMan 2 Created page with "<ref>https://en.m.wikipedia.org/wiki/Chemistry</ref>" wikitext text/x-wiki <ref>https://en.m.wikipedia.org/wiki/Chemistry</ref> 88420ece0bfc56edc434d3300325efc46f12c52f Canopus 0 37 382 350 2023-07-07T05:43:07Z SpaceMan 2 wikitext text/x-wiki {{short description|Bright giant star in the constellation of Carina}} {{Other uses}} {{Starbox begin | name=Canopus }} {{Starbox image | image=[[File:Canopus.jpg|255px]] | caption=An image of Canopus by [[Expedition 6]] }} {{Starbox observe | epoch=J2000 | constell=[[Carina (constellation)|Carina]] | pronounce={{IPAc-en|k|ə|ˈ|n|oʊ|p|ə|s}}<ref>{{OED|Canopus}}</ref> | ra={{RA|06|23|57.10988}}<ref name="van Leeuwen2007">{{cite journal | title=Validation of the new Hipparcos reduction | last1=van Leeuwen | first1=F. | journal=Astronomy and Astrophysics | volume=474 | issue=2 | pages=653–664 | date=2007 | arxiv=0708.1752 | bibcode=2007A&A...474..653V | doi=10.1051/0004-6361:20078357 | s2cid=18759600 }} [http://webviz.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b48255b3&-out.add=.&-source=I/311/hip2&recno=30362 Vizier catalog entry ]</ref> | dec={{DEC|-52|41|44.3810}}<ref name="van Leeuwen2007"/> | appmag_v=−0.74<ref name="Ducati 2002">{{cite journal | title=Catalogue of Stellar Photometry in Johnson's 11-color system | last1=Ducati | first1=J. R. | journal=CDS/ADC Collection of Electronic Catalogues | volume=2237 | pages=0 | date=2002 | bibcode=2002yCat.2237....0D }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b360304a&-out.add=.&-source=II/237/colors&recno=1155 Vizier catalog entry ]</ref> }} {{Starbox character | type= | class=A9&nbsp;II<ref name=perkins>{{cite journal|bibcode=1989ApJS...69..301G|title=The early F-type stars – Refined classification, confrontation with Stromgren photometry, and the effects of rotation|journal=Astrophysical Journal Supplement Series|volume=69|pages=301|last1=Gray|first1=R. O.|last2=Garrison|first2=R. F.|year=1989|doi=10.1086/191315}}</ref><ref>{{cite journal|bibcode=1993ASPC...45...59L|title=A Spectroscopic Study of High Galactic Latitude F Supergiant Stars|journal=Luminous High-Latitude Stars. The International Workshop on Luminous High-Latitude Stars|volume=45|pages=59|last1=Lopez-Cruz|first1=O.|last2=Garrison|first2=R. F.|year=1993}}</ref> | b-v=+0.15<ref name="Ducati 2002"/> | u-b=+0.10<ref name="Ducati 2002"/> | variable= }} {{Starbox astrometry | radial_v={{val|20.3|0.5}}<ref name="Gontcharov 2007">{{cite journal | title=Pullkovo Compilation of Radial Velocities for 39495 Hipparcos stars in a common system | last1=Gontcharov | first1=G. A. | journal=Astronomy Letters | volume=32 | issue=1 | pages=759–771 | date=2007 | bibcode=2006AstL...32..759G | doi=10.1134/S1063773706110065|arxiv = 1606.08053 | s2cid=119231169 }} [http://vizier.u-strasbg.fr/viz-bin/VizieR-5?-ref=VIZ53e6b5f60fbd&-out.add=.&-source=III/252/table8&recno=9232 Vizier catalog entry ]</ref> | prop_mo_ra=19.93<ref name="van Leeuwen2007"/> | prop_mo_dec=23.24<ref name="van Leeuwen2007"/> | parallax=10.55 | p_error=0.56 | parallax_footnote=<ref name="van Leeuwen2007"/> | absmag_v=–5.71<ref name=smiljanic2006/> |arxiv = 1606.08053 }} {{Starbox detail | metal_fe=–0.07<ref name=smiljanic2006/> | mass={{Val|8.0|0.3}}<ref name=vlti>{{cite journal|bibcode=2013MNRAS.434..437C|arxiv=1306.3288|title=Fundamental parameters of 16 late-type stars derived from their angular diameter measured with VLTI/AMBER|journal=Monthly Notices of the Royal Astronomical Society|volume=434|issue=1|pages=437–450|last1=Cruzalèbes|first1=P.|last2=Jorissen|first2=A.|last3=Rabbia|first3=Y.|last4=Sacuto|first4=S.|last5=Chiavassa|first5=A.|last6=Pasquato|first6=E.|last7=Plez|first7=B.|last8=Eriksson|first8=K.|last9=Spang|first9=A.|last10=Chesneau|first10=O.|year=2013|doi=10.1093/mnras/stt1037|s2cid=49573767}}</ref>&nbsp;(2013)<br/>{{val|10.1|0.1}}<ref name=Tetzlaff2011/>&nbsp;(2011) | radius={{Val|71|4}}<ref name=vlti/>&nbsp;(2013)<br>{{val|73.3|5.2}}<ref name=DomicianoDeSouza>{{cite journal|doi=10.1051/0004-6361/202140478|title=Refined fundamental parameters of Canopus from combined near-IR interferometry and spectral energy distribution|year=2021|last1=Domiciano De Souza|first1=A.|last2=Zorec|first2=J.|last3=Millour|first3=F.|last4=Le Bouquin|first4=J.-B.|last5=Spang|first5=A.|last6=Vakili|first6=F.|journal=Astronomy & Astrophysics|volume=654|pages=A19|arxiv=2109.07153|bibcode=2021A&A...654A..19D|s2cid=237513623}}</ref>&nbsp;(2021) | gravity={{Val|1.70|0.05}}<ref name=DomicianoDeSouza/> | rotational_velocity=9<ref name=ayres2018/> | rotation={{val|298|u=days|p=≥}}<ref name=Testa2004/> | luminosity=10,700<ref name=vlti/> | temperature=7,400<ref name=ayres2018>{{cite journal |bibcode=2018ApJ...854...95A |title=Cracking the Conundrum of F-supergiant Coronae |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |year=2018 |volume=854 |issue=2 |page=95 |doi=10.3847/1538-4357/aaa6d7 |arxiv=1802.02552 |s2cid=119101035 }}</ref> | age_myr = {{val|25.1|2.5}}<ref name=Tetzlaff2011>{{cite journal | title=A catalogue of young runaway Hipparcos stars within 3 kpc from the Sun | last1=Tetzlaff | first1=N. | last2=Neuhäuser | first2=R. | last3=Hohle | first3=M. M. | journal=Monthly Notices of the Royal Astronomical Society | volume=410 | issue=1 | pages=190–200 | date=January 2011 | doi=10.1111/j.1365-2966.2010.17434.x | arxiv=1007.4883 | bibcode=2011MNRAS.410..190T | s2cid=118629873 }}</ref> }} {{Starbox catalog | names={{odlist | name=Suhayl | name2=Suhel | name3=Suhail | B=α Carinae | CPD=−52°1941 | FK5=245 | HD=45348 | HIP=30438 | HR=2326 | SAO=234480| GC=8302 }}<ref name=SIMBAD>{{cite simbad | title=alf Car | access-date=2019-03-09 }}</ref> }} {{Starbox reference | Simbad=canopus }} {{Starbox end}} '''Canopus''' is the brightest star in the southern [[constellation]] of [[Carina (constellation)|Carina]] and the [[list of brightest stars|second-brightest star]] in the [[night sky]]. It is also [[Bayer designation|designated]] '''α&nbsp;Carinae''', which is [[Latinisation of names|Latinised]] to '''Alpha&nbsp;Carinae'''. With a [[visual apparent magnitude]] of −0.74, it is outshone only by [[Sirius]]. Located around {{val|310|ul=light-years}} from the [[Sun]], Canopus is a [[bright giant]] of [[spectral type A9]], so it is essentially white when seen with the naked eye. It has a luminosity over 10,000 times the [[luminosity of the Sun]], is eight times as [[mass of the Sun|massive]], and has expanded to 71 times the [[Sun's radius]]. Its enlarged [[photosphere]] has an [[effective temperature]] of around {{val|7,400|fmt=commas|u=K}}. Canopus is undergoing [[stellar core|core]] [[helium fusion|helium burning]] and is currently in the so-called [[blue loop]] phase of its [[stellar evolution|evolution]], having already passed through the [[red-giant branch]] after exhausting the hydrogen in its core. Canopus is a [[X-ray astronomy|source of X-rays]], which are likely being emitted from its [[stellar corona|corona]]. The prominent appearance of Canopus means it has been the subject of mythological lore among many ancient peoples. Its proper name is generally considered to originate from the [[Greek mythology|mythological]] [[Canopus (mythology)|Canopus]], who was a navigator for [[Menelaus]], king of [[Sparta]]. The [[acronychal rising]] marked the date of the Ptolemaia festival in Egypt. In ancient India, it was named [[Agastya]] after the revered [[Vedas|Vedic]] sage. For Chinese astronomers, it was known as the [[Old Man of the South Pole]]. ==Nomenclature== The name ''Canopus'' is a Latinisation of the [[Ancient Greek]] name Κάνωβος/Kanôbos, recorded in Claudius Ptolemy's ''[[Almagest]]'' (c.150 AD). Eratosthenes used the same spelling.<ref name="ridpathCr"/> Hipparchos wrote it as Κάνωπος. [[John Flamsteed]] wrote Canobus,<ref>{{cite book|last=Flamsteed|first=John|title=Atlas coelestis|location=London, United Kingdom|date=1729|pages=Constellation Map of Southern Hemisphere|url=http://lhldigital.lindahall.org/u?/astro_atlas,1191}}</ref> as did [[Edmond Halley]] in his 1679 ''Catalogus Stellarum Australium''.<ref name="Halley 1679">{{cite book|last=Halley|first=Edmond|title=Catalogus stellarum australium; sive, Supplementum catalogi Tychenici, exhibens longitudines et latitudines stellarum fixarum, quae, prope polum Antarcticum sitae, in horizonte Uraniburgico Tychoni inconspicuae fuere, accurato calculo ex distantiis supputatas, & ad annum 1677 completum correctas...Accedit appendicula de rebus quibusdam astronomicis|publisher=T. James|location=London|date=1679|pages=30|url=http://babel.hathitrust.org/cgi/pt?id=mdp.39015007000170;view=1up;seq=41;size=150}}</ref> The name has two possible derivations, both listed in [[Richard Hinckley Allen]]'s seminal ''[[Star Names: Their Lore and Meaning]]''. * [[Argo Navis]] was the ship used by [[Jason]] and the Argonauts in the legend of the [[Trojan War]]. The brightest star in the constellation was given the name of a ship's pilot from another Greek legend: [[Canopus (mythology)|Canopus]], pilot of [[Menelaus]]' ship on his quest to retrieve [[Helen of Troy]] after she was taken by [[Paris (mythology)|Paris]].<ref name="hinkley63">{{cite book|first=Richard Hinckley|last=Allen|author-link=Richard Hinckley Allen|date=1963|orig-year=1899|title=Star Names: Their Lore and Meaning|pages=[https://archive.org/details/starnamestheirlo00alle/page/67 67–72]|edition=Revised|publisher=Dover Publications|location=New York|isbn=0-486-21079-0|url-access=registration|url=https://archive.org/details/starnamestheirlo00alle/page/67}}</ref> * A ruined ancient Egyptian port named [[Canopus, Egypt|Canopus]] lies near the mouth of the [[Nile]], site of the [[Battle of the Nile]]. It is speculated that its name is derived from the Egyptian [[Coptic language|Coptic]] ''Kahi Nub'' ("Golden Earth"), which refers to how Canopus would have appeared near the horizon in [[ancient Egypt]], reddened by atmospheric extinction from that position.<ref name="hinkley63"/><ref name=lynn1905>{{cite journal |bibcode=1905Obs....28..289L |title=The brightest fixed star and its name |last1=Lynn |first1=W. T. |journal=The Observatory |year=1905 |volume=28 |page=289 }}</ref> In 2016, the [[International Astronomical Union]] organized a [[IAU Working Group on Star Names|Working Group on Star Names]] (WGSN) to catalog and standardize proper names for stars.<ref name="WGSN">{{cite web | url=https://www.iau.org/science/scientific_bodies/working_groups/280/ | title=IAU Working Group on Star Names (WGSN) | website=iau.org | publisher=[[International Astronomical Union]] | access-date=22 May 2016}}</ref> The WGSN's first bulletin of July 2016 included a table of the first two batches of names approved by the WGSN, which included ''Canopus'' for this star.<ref name="WGSN1">{{cite web | url=https://www.iau.org/static/science/scientific_bodies/working_groups/280/WGSN_bulletin1.pdf | title=Bulletin of the IAU Working Group on Star Names, No. 1 | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06 }}</ref> Canopus is now included in the ''IAU Catalog of Star Names''.<ref name="IAU-CSN">{{cite web | url=https://www.iau.org/public/themes/naming_stars/ | title=IAU Catalog of Star Names | website=iau.org | publisher=International Astronomical Union | access-date=2020-09-06}}</ref> Canopus traditionally marked the rudder of the ship [[Argo Navis]].<ref>{{cite journal | title = On Frederick de Houtman's Catalogue of Southern Stars, and the Origin of the Southern Constellations | last1= Knobel|first1=E. B. |journal = [[Monthly Notices of the Royal Astronomical Society]] | volume= 77| issue= 5 | pages=414–432 [422] | bibcode = 1917MNRAS..77..414K |date=1917 | doi=10.1093/mnras/77.5.414| doi-access=free }}</ref> German celestial cartographer [[Johann Bayer]] gave it—as the brightest star in the constellation—the [[Bayer designation|designation]] of ''α&nbsp;Argus'' ([[Latinisation of names|Latinised]] to ''Alpha Argus'') in 1603. In 1763, French astronomer [[Nicolas Louis de Lacaille]] divided the huge constellation into three smaller ones,<ref name=Glass2012>{{cite book | title=Nicolas-Louis De La Caille, Astronomer and Geodesist | first=Ian Stewart | last=Glass | date=November 17, 2012 | page=73 | isbn=9780191649608 | publisher=OUP Oxford | url=https://www.google.com/books/edition/Nicolas_Louis_De_La_Caille_Astronomer_an/eZjlHAIBeRAC?hl=en&gbpv=1&pg=PT73 }}</ref> and hence Canopus became ''α&nbsp;Carinae'' ([[Latinisation of names|Latinised]] to ''Alpha Carinae''). It is listed in the [[Bright Star Catalogue]] as HR 2326, the [[Henry Draper Catalogue]] as HD 45348, and the [[Hipparcos catalogue]] as HIP 30438.<ref name=SIMBAD/> Flamsteed did not number this southern star, but [[Benjamin Apthorp Gould]] gave it the number 7 (7 G. Carinae) in his ''Uranometria Argentina''.<ref name=Gould1878>{{cite journal | title=Uranometria Argentina: Brightness and position of every fixed star, down to the seventh magnitude, within one hundred degrees of the South Pole; with atlas | last=Gould | first=Benjamin Apthorp | journal=Resultados del Observatorio Nacional Argentino | volume=1 | page=140 | date=1878 | bibcode=1879RNAO....1....1G }}</ref> An occasional name seen in English is ''Soheil'', or the feminine Soheila; in Turkish is ''Süheyl'', or the feminine Süheyla, from the Arabic name for several bright stars, سهيل ''suhayl'',<ref name="hinkley63"/> and Canopus was known as Suhel {{IPAc-en|'|s|uː|h|E|l}} in medieval times.<ref name=kunitzsch/> Alternative spellings include Suhail, Souhail, Suhilon, Suheyl, Sohayl, Suhayil, Shoel, Sohil, Soheil, Sahil, Suhayeel, Sohayil, Sihel, and Sihil.<ref name="hinkley63"/> An alternative name was ''Wazn'' "weight" or ''Haḍar'' "ground", possibly related to its low position near the horizon.<ref name="hinkley63"/> Hence comes its name in the ''[[Alfonsine tables]]'', Suhel ponderosus, a Latinization of ''Al Suhayl al Wazn''.<ref name="hinkley63"/> Its Greek name was revived during the [[Renaissance]].<ref name=kunitzsch>{{cite book |last1=Kunitzsch|first1=Paul |last2=Smart|first2=Tim |date = 2006|title = A Dictionary of Modern star Names: A Short Guide to 254 Star Names and Their Derivations |edition = 2nd rev. |publisher = Sky Publishing Corporation |location = Cambridge, Massachusetts |isbn = 978-1-931559-44-7 |page = 23}}</ref> ==Observation== [[File:Carina constellation map.svg|thumb|left|The constellation [[Carina (constellation)|Carina]] with Canopus towards the right (west)]] The Spanish Muslim astronomer [[Ibn Rushd]] went to [[Marrakesh]] (in Morocco) to observe the star in 1153, as it was invisible in his native [[Córdoba, Spain|Córdoba]], [[Al-Andalus]]. He used the different visibility in different latitudes to argue that the [[Spherical Earth|earth is round]], following [[Spherical Earth#Aristotle|Aristotle's argument]] which held that such an observation was only possible if the earth was a relatively small sphere.<ref name=ibn_rushd>{{cite encyclopedia|first1=Juan|last1=Vernet|author-link1=Juan Vernet|first2=Julio|last2=Samsó|author-link2=Julio Samsó |title=The development of Arabic science in Andalusia |page=264|editor=[[Roshdi Rashed]]|encyclopedia=Encyclopedia of the History of Arabic Science | date=1996|publisher=Routledge|isbn=978-0-415-12410-2|oclc=912501823}}</ref> English explorer [[Robert Hues]] brought Canopus to the attention of European observers in his 1592 work ''Tractatus de Globis'', along with [[Achernar]] and [[Alpha Centauri]], noting:<blockquote>"Now, therefore, there are but three [[First-magnitude star|Stars of the first magnitude]] that I could perceive in all those parts which are never seene here in England. The first of these is that bright Star in the sterne of [[Argo Navis|Argo]] which they call Canobus. The second is in the end of [[Eridanus (constellation)|Eridanus]]. The third is in the right foote of the [[Centaurus|Centaure]]."<ref>Knobel, p. 416.</ref></blockquote> [[File:Vela and Surrounding Constellations (ground-based image).jpg|right|thumb|Wide angle view showing Canopus and other prominent stars with the Milky Way|alt=A field of stars against the Milky Way background with the prominent stars and constellations labelled]] In the [[Southern Hemisphere]], Canopus and [[Sirius]] are both visible high in the sky simultaneously, and reach a [[meridian (astronomy)|meridian]] just {{val|21|u=minutes}} apart. Brighter than [[first-magnitude star|first magnitude]], Canopus can be seen by naked eye in the early twilight. Mostly visible in mid to late summer in the Southern Hemisphere, Canopus [[Culmination|culminates]] at midnight on December 27,<ref name="motz" /> and at 9 PM on February 11.<ref name="Schaaf257">Schaaf, p. 257.</ref> When seen from latitudes south of {{DEC|37|18}}&nbsp;S, Canopus is a [[circumpolar star]]. Since Canopus is so far south in the sky, it never rises in mid- to far-northern latitudes; in theory the northern limit of visibility is latitude {{DEC|37|18}} north. This is just south of [[Athens]], [[Richmond, Virginia]] (USA), and [[San Francisco]], and very close to [[Seville]] and [[Agrigento]]. It is almost exactly the latitude of [[Lick Observatory]] on [[Mount Hamilton (California)|Mt. Hamilton, California]], from which it is readily visible because of the effects of elevation and [[atmospheric refraction]], which add another degree to its apparent altitude. Under ideal conditions, it can be spotted as far north as latitude {{DEC|37|31}} from the Pacific coast.<ref>D. Gieringer, "Exploring the Tropic of Canopus", ''Astronomy'', December 1985, p.24.</ref> Another northernmost record of visibility came from [[Mount Nemrut]] in Turkey, latitude {{DEC|37|59}}.<ref>{{cite web |last1=Tezel |first1=Tunç |author-link=Tunç Tezel |url=http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |title=Zodiacal Light and Nemrut Heritage |work=The World At Night (TWAN) |access-date=17 March 2014 |date=8 Oct 2013 |archive-url=https://web.archive.org/web/20140317134955/http://www.twanight.org/newTWAN/photos.asp?ID=3004572 |archive-date=17 March 2014 |url-status=dead }}</ref> It is more easily visible in places such as the Gulf Coast and Florida, and the island of [[Crete]] (Greece) where the best season for viewing it around 9 p.m. is during late January and early February.<ref name="motz">{{cite book|last1=Motz|first1=Lloyd|last2=Nathanson|first2=Carol|title=The Constellations: An Enthusiast's Guide to the Night Sky|publisher=Aurum Press|location=London, United Kingdom|date=1991|pages=376–77|isbn=1-85410-088-2}}</ref> Canopus has a B–V [[color index]] of +0.15—where 0 is a blue-white—indicating it is essentially white, although it has been described as yellow-white. Canopus' spectral type has been given as F0 and the incrementally warmer A9. It is less yellow than [[Altair]] or [[Procyon]], with indices measured as 0.22 and 0.42, respectively.<ref name=Hoffleit1991>{{cite book | title=Bright Star Catalogue | edition=5th Revised | last1=Hoffleit | first1=D. | last2=Warren Jr. | first2=W. H. | date=1991 | publisher=[[Centre de Données astronomiques de Strasbourg|CDS]] }}</ref> Some observers may have perceived Canopus as yellow-tinged because it is low in the sky and hence subject to atmospheric effects.<ref name="Schaaf112">Schaaf, pp. 112–13.</ref> [[Patrick Moore]] said that it never appeared anything but white to him.<ref name="moore2000">{{cite book | first1=Patrick | last1=Moore | title=Exploring the night sky with binoculars | edition=4th | publisher=Cambridge University Press | year=2000 | isbn=9780521793902 | page=[https://archive.org/details/exploringnightsk00moor/page/69 69] | url=https://archive.org/details/exploringnightsk00moor| url-access=registration }}</ref> The [[bolometric correction]] for Canopus is 0.00,<ref name=smiljanic2006/> indicating that the visual [[absolute magnitude]] and bolometric absolute magnitude are equal. Canopus was previously proposed to be a member of the [[Scorpius–Centaurus association]], however it is not located near the subgroups of that association, and has not been included as a Sco-Cen member in kinematic studies that used [[Hipparcos]] astrometric data.<ref name="deZeeuw">{{cite journal|last1=de Zeeuw|first1=P.T. |last2=Hoogerwerf|first2=R. |last3=de Bruijne|first3=J.H.J |last4=Brown|first4=A.G.A |last5=Blaauw|first5=A. |date=1999|title=A HIPPARCOS Census of the Nearby OB Associations |journal=The Astronomical Journal |volume=117 |issue=1 |pages=354–399|bibcode=1999AJ....117..354D |doi=10.1086/300682|arxiv = astro-ph/9809227 |s2cid=16098861 }}</ref> Canopus is not thought to be a member of any nearby young stellar groups.<ref name=mamajek>{{cite journal | url=https://figshare.com/articles/Canopus_B_A_Candidate_Common_Proper_Motion_Companion_to_the_Second_Brightest_Star/1132696 | title=Canopus B: A Candidate Common Proper Motion Companion to the Second Brightest Star | last=Mamajek | first=Eric | year=2014 | publisher=Figshare | doi=10.6084/m9.figshare.1132696.v3 | access-date=2020-09-10 }}</ref> In 2014, astronomer Eric Mamajek reported that an extremely magnetically active M dwarf (having strong coronal X-ray emission), 1.16 degrees south of Canopus, appears to share a [[common proper motion]] with Canopus. The projected separation of the M dwarf 2MASS J06234738-5351131 ("Canopus B") is approximately 1.9 parsecs. However, despite this large separation, it is still within the estimated tidal radius (2.9 parsecs) for the massive star Canopus.<ref name="mamajek"/> No star closer than Canopus is more luminous than it, and it has been the brightest star in Earth's night sky during three epochs over the past four million years. Other stars appear brighter only during relatively temporary periods, during which they are passing the Solar System much closer than Canopus. About 90,000 years ago, [[Sirius]] moved close enough that it became brighter than Canopus, and that will remain so for another 210,000 years. But in 480,000 years, as Sirius moves further away and appears fainter, Canopus will once again be the brightest, and will remain so for a period of about 510,000 years.<ref name="tomkin98">{{cite journal|last=Tomkin|first=Jocelyn|date=April 1998|title=Once and Future Celestial Kings|journal=Sky and Telescope|volume=95|issue=4|pages=59–63|bibcode=1998S&T....95d..59T}}</ref><!-- this all comes from same paper --> ===Role in navigation=== The southeastern wall of the [[Kaaba]] in [[Mecca]] is aligned with the rising point of Canopus, and is also named ''Janūb''.<ref>{{cite book|author=George Nicholas Atiyeh|title=The Book in the Islamic World: The Written Word and Communication in the Middle East|url=https://books.google.com/books?id=t4LEfpCW_kQC|date=1 January 1995|publisher=SUNY Press|isbn=978-0-7914-2473-5}}</ref> The [[Negev Bedouin|Bedouin]] people of the [[Negev]] and [[Sinai Peninsula|Sinai]] knew Canopus as ''Suhayl'', and used it and [[Polaris]] as the two principal stars for navigation at night. Because it disappears below the horizon in those regions, it became associated with a changeable nature, as opposed to always-visible Polaris, which was circumpolar and hence 'steadfast'.<ref>{{cite journal |last=Bailey |first=Clinton |date=1974 |title=Bedouin Star-Lore in Sinai and the Negev |journal=Bulletin of the School of Oriental and African Studies, University of London |volume=37 |issue=3 |pages=580–96 |type=abstract |doi=10.1017/S0041977X00127491 |jstor=613801|s2cid=131527348 }}</ref> The south [[celestial pole]] can be approximately located using Canopus and another bright star, [[Achernar]], as the three make an [[equilateral triangle]]. Canopus sits on an imaginary line that extends {{DEC|36}} one way to Sirius and {{DEC|37}} to the south celestial pole.<ref>{{Cite book| last1 = Heifetz| first1 = Milton| last2 = Tirion| first2 = Wil| title = A Walk Through the Heavens: A Guide to Stars and Constellations and Their Legends | date = 2007| publisher = [[Cambridge University Press]]| location = Cambridge | page = 38 | isbn=978-1-139-46138-2}}</ref> Canopus's brightness and location well off the [[ecliptic]] make it useful for space navigation. Many spacecraft carry a special camera known as a "Canopus [[star tracker|Star Tracker]]" plus a Sun sensor for [[Orientation (geometry)|attitude]] determination. [[Mariner 4]] used Canopus for [[Spin-stabilisation|second axis stabilisation]] (after locking on the Sun) in 1964, the first time a star had been used.<ref>{{cite book |last1=United States. National Aeronautics and Space Administration. Scientific and Technical Information Division |title=Astronautics and Aeronautics, 1964: Chronology on Science, Technology and Policy |date=1965 |publisher=Scientific and Technical Information Division, National Aeronautics and Space Administration |page=398 |url=https://books.google.com/books?id=ckkCAAAAIAAJ&pg=PA398}}</ref> ==Spectrum== Canopus was little-studied by western scientists before the 20th century. It was given a spectral class of F in 1897, an early use of this extension to [[Secchi class]] I, applied to those stars where the hydrogen lines are relatively weak and the [[calcium K line]] relatively strong.<ref>{{cite journal |bibcode=1897ApJ.....6..349P |title=Spectra of bright southern stars |last1=Pickering |first1=E. C. |last2=Cannon |first2=A. J. |journal=The Astrophysical Journal |year=1897 |volume=6 |page=349 |doi=10.1086/140407 }}</ref> It was given as a standard star of F0 in the [[Henry Draper Catalogue]], with the spectral type F0 described as having hydrogen lines half the strength of an A0 star and the calcium K line three times as strong as Hδ.<ref name=hd>{{cite journal |bibcode=1918AnHar..92....1C |title=The Henry Draper catalogue : 4h, 5h and 6h |last1=Cannon |first1=Annie Jump |last2=Pickering |first2=Edward Charles |journal=Annals of Harvard College Observatory |year=1918 |volume=92 |page=1 }}</ref> American astronomer [[Jesse L. Greenstein|Jesse Greenstein]] was interested in stellar spectra and used the newly built [[Otto Struve Telescope]] at [[McDonald Observatory]] to analyze the star's spectrum in detail.<ref>{{cite book |last1=Trimble |first1=Virginia | first2= Thomas R. |last2=Williams | first3= Katherine | last3=Bracher| first4= Richard | last4=Jarrell| first5=Jordan D.| last5= Marché| first6=F. Jamil | last6=Ragep |title=Biographical Encyclopedia of Astronomers |date=2007 |publisher=Springer Science & Business Media |location=New York, New York |isbn=978-0-387-30400-7 |page=438 |url=https://books.google.com/books?id=t-BF1CHkc50C&pg=PA438}}</ref> In a 1942 paper, he reported that the spectrum is dominated by strong broad hydrogen lines. There are also [[absorption line]]s of carbon, nitrogen, oxygen, sulphur, iron, and many ionised metals.<ref name=greenstein1942>{{cite journal |bibcode=1942ApJ....95..161G |title=The Spectrum of α Carinae |last1=Greenstein |first1=Jesse L. |journal=The Astrophysical Journal |year=1942 |volume=95 |page=161 |doi=10.1086/144382 }}</ref> It was studied in the [[ultraviolet]] by an early astronomical satellite, [[Gemini XI]] in 1966. The UV spectra were considered to be consistent with an F0 [[Supergiant star|supergiant]] having a temperature of {{val|6,900|fmt=commas|u=K}}, the accepted parameters for Canopus at the time.<ref name=kondo1970>{{cite journal |bibcode=1970ApJ...159..927K |title=Ultraviolet Spectrophotometry of Canopus from Gemini XI |last1=Kondo |first1=Y. |last2=Henize |first2=K. G. |last3=Kotila |first3=C. L. |journal=The Astrophysical Journal |year=1970 |volume=159 |page=927 |doi=10.1086/150370 }}</ref> New Zealand-based astronomers [[John Hearnshaw]] and Krishna Desikachary examined the spectrum in greater detail, publishing their results in 1982.<ref>{{cite journal |title=The spectrum of Canopus | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 198 | year= 1982 | issue= 2 | pages= 311–320 | doi= 10.1093/mnras/198.2.311 | bibcode=1982MNRAS.198..311H| doi-access= free }}</ref><ref>{{cite journal |title=The spectrum of Canopus II - Analysis and composition | last1= Hearnshaw | first1= J. B.| last2= Desikachary | first2= K. | journal= Monthly Notices of the Royal Astronomical Society | volume= 201 | year= 1982 | issue= 3 | pages= 707–721 | doi= 10.1093/mnras/201.3.707 | bibcode=1982MNRAS.201..707D| doi-access= free }}</ref> When [[luminosity class]]es were added to the MK spectral classification scheme, Canopus was assigned class Iab indicating an intermediate luminosity supergiant. This was based on the relative strengths of certain spectral lines understood to be sensitive to the luminosity of a star.<ref name=devaucoleurs>{{cite journal|title=Spectral types and luminosities of B, A and F southern stars|author=de Vaucouleurs, A.|journal=Monthly Notices of the Royal Astronomical Society|volume=117|page=449|date=1957|issue=4|bibcode=1957MNRAS.117..449D|doi=10.1093/mnras/117.4.449|doi-access=free}}</ref> In the [[Bright Star Catalogue]] 5th edition it is given the spectral class F0II, the luminosity class indicating a [[bright giant]].<ref name=bsc>{{cite book |bibcode=1991bsc..book.....H |year=1991 |title=The Bright star catalogue |last1=Hoffleit |first1=Dorrit |last2=Jaschek |first2=Carlos }}</ref> [[Balmer line]] profiles and oxygen line strengths indicate the size and luminosity of Canopus.<ref name=kovtyukh2012>{{cite journal |bibcode=2012MNRAS.423.3268K |title=Accurate luminosities from the oxygen λ7771-4 Å triplet and the fundamental parameters of F-G supergiants |last1=Kovtyukh |first1=V. V. |last2=Gorlova |first2=N. I. |last3=Belik |first3=S. I. |journal=Monthly Notices of the Royal Astronomical Society |year=2012 |volume=423 |issue=4 |page=3268 |doi=10.1111/j.1365-2966.2012.21117.x |arxiv=1204.4115 |s2cid=118683158 }}</ref> When the effects of stellar rotation speed on spectral lines are accounted for, the MK spectral class of Canopus is adjusted to A9II.<ref name=perkins/> Its spectrum consists mostly of absorption lines on a visible [[continuous spectrum|continuum]], but some emission has been detected. For example, the [[calcium K line]] have weak emission wings on each side of the strong central absorption line, first observed in 1966. The emission line profiles are usually correlated with the luminosity of the star as described by the [[Wilson-Bappu effect]], but in the case of Canopus they indicate a luminosity much lower than that calculated by other methods.<ref name=warner1966>{{cite journal|title=CA II emission in the spectrum of Canopus|journal=The Observatory |volume=86 |pages=82|date=April 1966|last=Warner |first=B. |bibcode=1966Obs....86...82W }}</ref> More detailed observations have shown that the emission line profiles are variable and may be due to [[plage (astronomy)|plage]] areas on the surface of the star. Emission can also be found in other lines such as the h and k lines of ionised magnesium.<ref name=bappu1984>{{cite journal |bibcode=1984BASI...12..196B |title=CA II K emission in Canopus |last1=Bappu |first1=M. K. V. |last2=Mekkaden |first2=M. V. |last3=Rao |first3=N. K. |journal=Bulletin of the Astronomical Society of India |year=1984 |volume=12 |page=196 }}</ref> ==Distance== Before the launch of the [[Hipparcos]] satellite telescope, distance estimates for Canopus varied widely, from 96 [[light-year]]s to 1200 light-years. The closer distance was derived from parallax measurements of around {{val|33|ul=mas}}.<ref name=vandekamp1943>{{cite journal |title=Note on the Parallax of Canopus|journal=Popular Astronomy |volume=51 |date=1943 |page=172 |last=van de Kamp |first=Peter|bibcode=1943PA.....51..172V }}</ref> The larger distance derives from the assumption of a very bright [[absolute magnitude]] for Canopus.<ref name=vanzyl>{{cite book|author=J.E. van Zyl|title=Unveiling the Universe: An Introduction to Astronomy|url=https://books.google.com/books?id=Cj7uBwAAQBAJ&pg=PA184|date=6 December 2012|publisher=Springer Science & Business Media|isbn=978-1-4471-1037-8|pages=184–}}</ref> Hipparcos established Canopus as being {{val|310|u=light-years}} ({{val|95|ul=parsecs}}) from the [[Solar System]]; this is based on its 2007 [[parallax]] measurement of {{Val|10.43|0.53|ul=mas}}.<ref name="van Leeuwen2007"/> At 95 parsecs, the [[interstellar extinction]] for Canopus is low at 0.26 magnitudes.<ref name=DomicianoDeSouza/> Canopus is too bright to be included in the normal observation runs of the [[Gaia satellite]] and there is no published Gaia parallax for it.<ref name=dr2>{{cite DR2}}</ref> At present the star is drifting further away from the Sun with a [[radial velocity]] of 20&nbsp;km/s. Some 3.1&nbsp;million years ago it made the closest approach to the Sun at a distance of about {{convert|52.87|pc|ly|0|adj=ri0|order=flip|abbr=on|lk=off}}. Canopus is orbiting the Milky Way with a heliocentric velocity of 24.5&nbsp;km/s and a low [[orbital eccentricity|eccentricity]] of 0.065.<ref name=Anderson2012>{{citation | last1=Anderson | first1=E. | last2=Francis | first2=Ch. | title=XHIP: An extended hipparcos compilation | journal=Astronomy Letters | volume=38 | issue=5 | pages=331 | year=2012 | bibcode=2012AstL...38..331A | arxiv=1108.4971 | doi=10.1134/S1063773712050015 | s2cid=119257644 | postscript=. }}</ref> ==Physical characteristics== [[File:Constellation_Carina.jpg|thumb|right|upright|Canopus is the brightest star in the constellation of Carina (top).]] The [[absorption line]]s in the spectrum of Canopus shift slightly with a period of {{val|6.9|u=days}}. This was first detected in 1906 and the [[doppler effect|Doppler]] variations were interpreted as orbital motion.<ref name=curtis1907>{{cite journal |bibcode=1907PASP...19R.259C |title=The orbits of the spectroscopic binaries alpha Carinae, kappa Velorum, and alpha Pavonis |last1=Curtis |first1=H. D. |journal=Publications of the Astronomical Society of the Pacific |year=1907 |volume=19 |page=259 |doi=10.1086/121781 }}</ref> An orbit was even calculated, but no such companion exists and the small radial velocity changes are due to movements in the atmosphere of the star. The maximum observed [[radial velocities]] are only 0.7 to {{val|1.6|ul=km/s}}. Canopus also has a magnetic field that varies with the same period, detected by the [[Zeeman splitting]] of its spectral lines.<ref name=weiss1986>{{cite journal |bibcode=1986A&A...160..243W | title=The magnetic field of Canopus | last=Weiss | first=W. W. | journal= Astronomy and Astrophysics |volume= 160|pages= 243–250 | year=1986}}</ref> Canopus is bright at [[microwave]] wavelengths, one of the few F-class stars to be detected by radio.<ref name=gudel2002>{{cite journal |bibcode=2002ARA&A..40..217G |title=Stellar Radio Astronomy: Probing Stellar Atmospheres from Protostars to Giants |last1=Güdel |first1=Manuel |journal=Annual Review of Astronomy and Astrophysics |year=2002 |volume=40 |pages=217–261 |doi=10.1146/annurev.astro.40.060401.093806 |arxiv=astro-ph/0206436 |s2cid=53633983 }}</ref> The [[rotation period]] of the star is not accurately known, but may be over three hundred days.<ref name=Testa2004>{{cite journal | title=The Density of Coronal Plasma in Active Stellar Coronae | last1=Testa | first1=Paola | last2=Drake | first2=Jeremy J. | last3=Peres | first3=Giovanni | journal=The Astrophysical Journal | volume=617 | issue=1 | pages=508–530 | date=December 2004 | doi=10.1086/422355 | arxiv=astro-ph/0405019 | bibcode=2004ApJ...617..508T | s2cid=17532089 }}</ref> The [[projected rotational velocity]] has been measured at 9&nbsp;km/s.<ref name=ayres2018/> An early [[Interferometry|interferometric]] measurement of its [[angular diameter]] in 1968 gave a [[Limb darkening|limb-darkened]] value of {{val|6.86|ul=mas}}, close to the accepted modern value.<ref>{{cite journal |bibcode=1968ARA&A...6...13B |title=Measurement of Stellar Diameters |last1=Brown |first1=R. Hanbury |journal=Annual Review of Astronomy and Astrophysics |year=1968 |volume=6 |page=13 |doi=10.1146/annurev.aa.06.090168.000305 }}</ref> [[Very-long-baseline interferometry]] has been used to calculate Canopus' angular diameter at {{val|6.9|ul=mas}}. Combined with distance calculated from its Hipparcos parallax, this gives it a radius of 71 times [[Solar radius|that of the Sun]].<ref name=vlti/> If it were at the centre of the Solar System, it would extend 90% of the way to the orbit of [[Mercury (planet)|Mercury]].<ref name=Kalerstars>{{cite web|url=http://stars.astro.illinois.edu/sow/canopus.html|title=Canopus|last=Kaler|first=Jim|work=Stars|publisher=University of Illinois|access-date=8 July 2012|date=26 June 2009}}</ref> The radius and temperature relative to the Sun means that it is 10,700 times more luminous than the Sun, and its position in the [[H-R diagram]] relative to theoretical [[stellar evolution|evolutionary]] tracks means that it is {{Val|8.0|0.3}} times as massive as the Sun.<ref name=vlti/> Measurements of its shape find a 1.1° departure from spherical symmetry.<ref name=cruzalebes2015>{{cite journal |bibcode=2015MNRAS.446.3277C |title=Departure from centrosymmetry of red giants and supergiants measured with VLTI/AMBER |last1=Cruzalèbes |first1=P. |last2=Jorissen |first2=A. |last3=Chiavassa |first3=A. |last4=Paladini |first4=C. |last5=Rabbia |first5=Y. |last6=Spang |first6=A. |journal=Monthly Notices of the Royal Astronomical Society |year=2015 |volume=446 |issue=4 |page=3277 |doi=10.1093/mnras/stu2382 |doi-access=free }}</ref> Canopus is a source of [[X-ray astronomy|X-rays]], which are probably produced by its corona, magnetically heated to several million [[Kelvin]]. The temperature has likely been stimulated by fast rotation combined with strong convection percolating through the star's outer layers.<ref name=ness>{{cite journal|bibcode=2004A&A...427..667N|title=On the sizes of stellar X-ray coronae|journal=Astronomy and Astrophysics|volume=427|issue=2|pages=667–683|last1=Ness|first1=J.-U.|last2=Güdel|first2=M.|last3=Schmitt|first3=J. H. M. M.|last4=Audard|first4=M.|last5=Telleschi|first5=A.|year=2004|doi=10.1051/0004-6361:20040504|arxiv = astro-ph/0407231 |s2cid=11468731}}</ref> The soft X-ray sub-coronal X-ray emission is much weaker than the hard X-ray coronal emission. The same behaviour has been measured in other F-class supergiants such as [[α Persei]] and is now believed to be a normal property of such stars.<ref name=ayres2018/> == Evolution == The spectrum of Canopus indicates that it has exhausted its core hydrogen and [[stellar evolution|evolved]] away from the [[main sequence]], where it spent some 30 million years of its existence as a blue-white star <!-- source suggests B2V but may be too exact --> of around 10 solar masses.<ref>{{cite journal |last1=Peimbert |first1=M. |last2=Wallerstein | first2= G.| last3= Pilachowski | first3= C. A. |title=An upper limit for the deuterium abundance in Canopus |journal=Astronomy and Astrophysics |date=1981 |volume=104 |issue=1 |pages=72–74 | bibcode=1981A&A...104...72P}}</ref> The position of Canopus in the [[H–R diagram]] indicates that it is currently in the core-helium burning phase.<ref name=vlti/> It is an intermediate mass star that has left the [[red-giant branch]] before its core became [[degenerate matter|degenerate]] and is now in a [[blue loop]].<ref name=desouza>{{Cite journal | last1 = Domiciano De Souza | first1 = A. | last2 = Bendjoya | first2 = P. | last3 = Vakili | first3 = F. | last4 = Millour | first4 = F. | last5 = Petrov | first5 = R. G. | title = Diameter and photospheric structures of Canopus from AMBER/VLTI interferometry | doi = 10.1051/0004-6361:200810450 | journal = Astronomy and Astrophysics | volume = 489 | issue = 2 | pages = L5–L8 | year = 2008 |bibcode = 2008A&A...489L...5D | url = https://hal.archives-ouvertes.fr/hal-00316994/document | doi-access = free }}</ref> Models of stellar evolution in the blue loop phase show that the length of the blue loop is strongly affected by rotation and mixing effects inside the star. It is difficult to determine whether a star is currently evolving towards hotter temperature or returning to cooler temperatures, since the evolutionary tracks for stars with different masses overlap during the blue loops.<ref name=smiljanic2006>{{cite journal |bibcode=2006A&A...449..655S |title=CNO in evolved intermediate mass stars |last1=Smiljanic |first1=R. |last2=Barbuy |first2=B. |last3=De Medeiros |first3=J. R. |last4=Maeder |first4=A. |journal=Astronomy and Astrophysics |year=2006 |volume=449 |issue=2 |page=655 |doi=10.1051/0004-6361:20054377 |arxiv=astro-ph/0511329 |s2cid=3711409 }}</ref> Canopus lies on the warm side of the [[instability strip]] and does not pulsate like [[Cepheid variables]] of a similar luminosity.<ref name=ayres2011>{{cite journal |doi=10.1088/0004-637X/738/2/120 |title=The Curious Case of the Alpha Persei Corona: A Dwarf in Supergiant's Clothing? |year=2011 |last1=Ayres |first1=Thomas R. |journal=The Astrophysical Journal |volume=738 |issue=2 |page=120 |bibcode=2011ApJ...738..120A |doi-access=free }}</ref> However its atmosphere does appear to be unstable, showing strong signs of convection.<ref name=smiljanic2006/> Canopus may not be massive enough for its [[nuclear fusion|fusion]] chain to reach iron and trigger a core collapse and subsequent [[supernova]], instead eventually becoming a neon-oxygen [[white dwarf]].<ref name=Kalerstars/> ==Cultural significance == Canopus was known to the ancient Mesopotamians and given the name ''NUN-ki'' and represented the city of [[Eridu]] in the ''Three Stars Each'' [[Babylonian star catalogues]] and later [[MUL.APIN]] around 1100 BC.<ref>{{cite journal | last = Rogers | first = John H. | date = 1998 | title = Origins of the Ancient Constellations: I. The Mesopotamian Traditions | journal = Journal of the British Astronomical Association | volume = 108 | issue = 1 | pages = 9–28 | bibcode = 1998JBAA..108....9R}}</ref> Today, the star [[Sigma Sagittarii]] is known by the common name Nunki.<ref name=allen>{{citation | page=359 | first1=Richard Hinckley | last1=Allen | title=Star Names, their lore and meaning}}</ref> Canopus was not visible to the mainland [[Ancient Greece|ancient Greeks]] and [[Roman Empire|Romans]]; it was, however, visible to the [[ancient Egypt]]ians.<ref name="Schaaf107">Schaaf, p. 107.</ref> Hence [[Aratus]] did not write of the star as it remained below the horizon, while [[Eratosthenes]] and [[Ptolemy]]—observing from [[Alexandria]]—did, calling it ''Kanōbos''.<ref name=ridpathCr>{{cite web| url=http://www.ianridpath.com/startales/carina.htm | title=Carina |last1=Ridpath|first1=Ian|publisher=self-published |work=Star Tales | access-date= 10 December 2015}}</ref> An [[Egypt]]ian priestly poet in the time of [[Thutmose III]] mentions the star as ''Karbana,'' "the star which pours his light in a glance of fire, when he disperses the morning dew."<ref name="hinkley63" /> Under the [[Ptolemies]], the star was known as ''Ptolemaion'' ([[Ancient Greek|Greek]]: Πτολεμαῖον) and its [[acronychal rising]] marked the date of the Ptolemaia festival, which was held every four years, from 262 to 145 BC.<ref>[[Martianus Capella]] 7.838, {{cite journal | last1 = Hazzard | last2 = Fitzgerald | year = 1991 | title = The Regulation of the Ptolemeia | journal = Journal of the Royal Astronomical Society of Canada | volume = 85 | pages = 6–23 |bibcode = 1991JRASC..85....6H }}; Hazzard. 2000. ''Imagination of a Monarchy: Studies in Ptolemaic Propaganda'', 34–36.</ref> [[File:Statue of Averroes in Córdoba, Spain.jpg|thumb|upright|[[Averroes]], who used his 1153 observation of Canopus in [[Marrakesh]] while the star was invisible in his native Spain as an argument that the [[Spherical Earth|earth is round]].<ref name=ibn_rushd/>]] ===India=== In Indian [[Vedas|Vedic literature]], Canopus is associated with the sage [[Agastya]], one of the ancient [[siddhar]]s and [[rishi]]s (the others are associated with the stars of the [[Big Dipper]]).<ref name="Frawley 1993">{{cite book|last=Frawley|first=David|title=Gods, Sages and Kings: Vedic Secrets of Ancient Civilization|publisher=Motilal Banarsidass |location=New Delhi, India|date=1993}}</ref> To Agastya, the star is said to be the 'cleanser of waters', and its rising coincides with the calming of the waters of the [[Indian Ocean]]. It is thus considered the son of [[Pulastya]], son of [[Brahma]]. Canopus is described by [[Pliny the Elder]] and [[Gaius Julius Solinus]] as the largest, brightest and only source of [[starlight]] for navigators near [[Tamraparni]] island (ancient Sri Lanka) during many nights.<ref>{{cite book |last1=Pridham |first1=Charles |title=An Historical, Political, and Statistical Account of Ceylon and Its Dependencies |date=1849 |publisher=T. and W. Boone |page=7 |url=https://books.google.com/books?id=O4aqHOMSJdYC&pg=PR19-IA5|language=en}}</ref><ref name="Frawley 1993"/><ref>{{cite book |last1=Elder |first1=Pliny the |title=Delphi Complete Works of Pliny the Elder (Illustrated) |date=2015 |publisher=Delphi Classics |url=https://books.google.com/books?id=OrJ0CgAAQBAJ&pg=PA343|language=en}}</ref> ===China=== Canopus was described as Shou Xing, the Star of Longevity, in the ''Shiji'' ([[Records of the Grand Historian]]) completed in 94 BC by Chinese historian [[Sima Qian]].<ref name=fong83>{{cite journal | title=The Iconography of the Popular Gods of Happiness, Emolument, and Longevity (Fu Lu Shou) | first=Mary H. |last=Fong | journal=Artibus Asiae | volume= 44 | issue= 2/3 | year=1983| pages= 159–199 | doi= 10.2307/3249596| jstor=3249596 }}</ref> Drawing on sources from the [[Warring States period]], he noted it to be the southern counterpart of [[Sirius]],<ref name="IDP"/> and wrote of a sanctuary dedicated to it established by Emperor [[Qin Shi Huang]] between 221 and 210 BC. During the [[Han dynasty]], the star was auspicious, its appearance in the southern sky heralding peace and absence war.<ref name=fong83/> From the imperial capital [[Chang'an]], the star made a low transit across the southern sky, indicating true south to observers, and was often obscured by clouds.<ref name=baumann19>{{cite journal | title=The White Old Man: Géluk-Mongolian Canopus Allegory and the Existence of God | first=Brian | last=Baumann | journal= Central Asiatic Journal | volume= 62 | issue= 1 | year=2019| pages= 35–68 | doi=10.13173/centasiaj.62.1.0035| s2cid=213083544 }}</ref> During this time it was also equated with [[Old Man of the South Pole]] (in {{zh|c=南极老人|p=Nanji Lǎorén}})<ref name=fong83/> Under this name, Canopus appears (albeit misplaced northwards) on the medieval Chinese manuscript the [[Dunhuang Star Chart]], although it cannot be seen from the Chinese capital of [[Chang'an]].<ref name="IDP">{{cite journal|bibcode=2009JAHH...12...39B|arxiv=0906.3034|title=The Dunhuang Sky: A Comprehensive Study of the Oldest Known Star Atlas|volume=12|issue=1|pages=39–59|last1=Bonnet-Bidaud|first1=Jean-Marc |last2=Praderie|first2=Françoise |last3=Whitfield|first3=Susan |author-link=Susan Whitfield |journal=The International Dunhuang Project: The Silk Road Online|year=2009}}</ref> The Chinese astronomer [[Yi Xing]] had journeyed south to chart Canopus and other far southern stars in 724 AD.<ref>{{cite book|last=Needham|first=Joseph|title=Science and Civilisation in China: Volume 3, Mathematics and the Sciences of the Heavens and the Earth|publisher=Cambridge University Press|location=Cambridge, United Kingdom|date=1959|pages=274|isbn=0521058015}}</ref> Its personification as the Old Man Star was popularised in the [[Tang Dynasty]], where it appeared often in poetry and memorials. Later still, during the [[Ming Dynasty]], the star was established as one of the [[Sanxing (deities)|Three Stars]] (Fu Lo Shou), appearing frequently in art and literature of the time.<ref name=fong83/> This symbolism spread into neighbouring cultures in Asia.<ref name=baumann19/> In Japan, Canopus is known as ''Mera-boshi'' and ''Roujin-sei'' (the old man star),<ref>{{cite conference |url=http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |title=Stellar Iconology and Astronomical Folklore in Japan |author=Takao Ibaraki |book-title=International Planetarium Society (IPS) Conferences 1996 |publisher=International Planetarium Society |location=Osaka |date=14 July 1996 |access-date=25 February 2012 |url-status=dead |archive-url=https://web.archive.org/web/20120326195757/http://www2.tba.t-com.ne.jp/october-country/ips96/japanese_star.html |archive-date=2012-03-26 }}</ref> and in Mongolia, it was personified as the White Old Man.<ref name=fong83/> Although the link was known in Tibet, with names such as ''Genpo karpo'' (''Rgan po dkar po'') or ''Genkar'' (''Rgan dkar'') "White Old Man", the symbolism was not popular. Instead, Canopus was more commonly named ''Karma Rishi སྐར་མ་རི་ཥི།'', derived from Indian mythology. Tibetans celebrated the star's heliacal rising with ritual bathing and associated it with morning dew.<ref name=baumann19/> ===Polynesia=== Bright stars were important to the ancient [[Polynesian culture|Polynesians]] for navigation between the many islands and atolls of the Pacific Ocean. Low on the horizon, they acted as stellar compasses to assist mariners in charting courses to particular destinations. Canopus served as the southern wingtip of a "Great Bird" constellation called ''Manu'', with Sirius as the body and [[Procyon]] the northern wingtip, which divided the Polynesian night sky into two hemispheres.<ref name="Holberg">{{cite book | last=Holberg | first=J.B. | title=Sirius: Brightest Diamond in the Night Sky | date=2007 | publisher=Praxis Publishing | location=Chichester, UK | isbn=978-0-387-48941-4 | pages=[https://archive.org/details/siriusbrightestd0000holb/page/25 25–26] | url=https://archive.org/details/siriusbrightestd0000holb/page/25 }}</ref> The [[Hawaiian people]] called Canopus ''Ke Alii-o-kona-i-ka-lewa'', "The chief of the southern expanse"; it was one of the stars used by [[Hawaiʻiloa]] and Ki when they traveled to the [[Southern Ocean]].{{sfn|Makemson|1941|p=198}} The [[Māori people]] of [[New Zealand|New Zealand/Aotearoa]] had several names for Canopus. ''[[Ariki]]'' ("High-born"), was known as a solitary star that appeared in the east, prompting people to weep and chant.{{sfn|Makemson|1941|p=201}} They also named it ''[[Atutahi]]'', ''Aotahi'' or ''Atuatahi'', "Stand Alone".<ref>p. 419, [https://books.google.com/books?id=p7dR2w1Wv2sC ''Mythology: Myths, Legends and Fantasies''], Janet Parker, Alice Mills, Julie Stanton, Durban, Struik Publishers, 2007.</ref> Its solitary nature indicates it is a ''[[Tapu (Polynesian culture)|tapu]]'' star, as ''tapu'' people are often solitary. Its appearance at the beginning of the ''Maruaroa'' season foretells the coming winter; light rays to the south indicate a cold wet winter, and to the north foretell a mild winter. Food was offered to the star on its appearance.<ref name="Best22">{{cite book|last=Best|first=Elsdon|title=Astronomical Knowledge of the Maori: Genuine and Empirical|publisher=Dominion Museum|location=Wellington, New Zealand|date=1922|pages=34–35|url=http://nzetc.victoria.ac.nz/tm/scholarly/tei-BesAstro-t1-body-d1-d6-d4.html}}</ref> This name has several mythologies attached to it. One story tells of how Atutahi was left outside the basket representing the [[Milky Way]] when [[Tāne]] wove it. Another related myth about the star says that Atutahi was the first-born child of [[Rangi and Papa|Rangi]], who refused to enter the Milky Way and so turned it sideways and rose before it. The same name is used for other stars and constellations throughout Polynesia.{{sfn|Makemson|1941|pp=200–202}} ''Kapae-poto'', "Short horizon", referred to it rarely setting as seen in New Zealand;{{sfn|Makemson|1941|p=217}} ''Kauanga'' ("Solitary") was the name for Canopus only when it was the last star visible before sunrise.{{sfn|Makemson|1941|p=218}} The people of the [[Society Islands]] had two names for Canopus, as did the [[Tuamotu]] people. The Society Islanders called Canopus ''Taurua-e-tupu-tai-nanu'', "Festivity-whence-comes-the-flux-of-the-sea", and ''Taurua-nui-o-te-hiti-apatoa'' "Great-festivity-of-the-border-of-the-south",{{sfn|Makemson|1941|p=259}} and the Tuamotu people called the star ''Te Tau-rari'' and ''Marere-te-tavahi'', the latter said to be the true name for the former, "He-who-stands-alone".{{sfn|Makemson|1941|p=229}} ===Africa=== In the [[Guanches|Guanche]] mythology of the island of [[Tenerife]] (Spain), the star Canopus was linked with the goddess [[Chaxiraxi]].<ref name="Rumeu">{{cite book|author=Antonio Rumeu de Armas|title=La conquista de Tenerife, 1494–1496|url=https://books.google.com/books?id=Ck4BAAAAMAAJ|year=1975|publisher=Aula de Cultura de Tenerife|isbn=9788450071078}}</ref> The [[Tswana people]] of [[Botswana]] knew Canopus as ''Naka''. Appearing late in winter skies, it heralded increasing winds and a time when trees lose their leaves. Stock owners knew it was time to put their sheep with rams.<ref>{{cite journal|last=Clegg|first=Andrew|date=1986|title=Some Aspects of Tswana Cosmology|journal=Botswana Notes and Records|volume=18|pages=33–37|jstor=40979758 }}</ref> In southern Africa, the Sotho, Tswana and Venda people called Canopus ''Naka'' or ''Nanga'', “the Horn Star”, while the Zulu and Swazi called it ''inKhwenkwezi'' "Brilliant star". It appears in the predawn sky in the third week of May. According to the Venda, the first person to see Canopus would blow a ''phalaphala'' horn from the top of a hill, getting a cow for a reward. The Sotho chiefs also awarded a cow, and ordered their medicine men to roll bone dice and read the fortune for the coming year.<ref name=snedegar95>{{cite journal |last1=Snedegar |first1=K.V. |title=Stars and seasons in Southern Africa |journal=Vistas in Astronomy |date=1995 |volume=39 |issue=4 |pages=529–38 |doi=10.1016/0083-6656(95)00008-9|bibcode=1995VA.....39..529S }}</ref> To the [[ǀXam language|ǀXam]]-speaking [[Bushmen]] of South Africa, Canopus and Sirius signalled the appearance of termites and flying ants. They also believed that stars had the power to cause death and misfortune, and they would pray to [[Sirius]] and Canopus in particular to impart good fortune or skill.<ref>{{cite journal| title="The Sky's Things", <nowiki>|</nowiki>xam Bushman 'Astrological Mythology' as recorded in the Bleek and Lloyd Manuscripts |last1=Hollman|first1=J. C.|journal=African Sky|volume= 11|page=8 |bibcode=2007AfrSk..11....8H|year = 2007 }}</ref> The [[ǃKung people]] of the [[Kalahari Desert]] in Botswana held Canopus and Capella to be the horns of ''tshxum'' (the Pleiades), the appearance of all three marking the end of the dry season and start of the rainy season.<ref>{{cite journal |last1=Marshall |first1=Lorna |title=Two Ju/ wa constellations |journal=Botswana Notes & Records |date=1975 |volume=7 |issue=1 |pages=153–159 | issn=0525-5090 |url=https://journals.co.za/docserver/fulltext/botnotes/7/1/548.pdf?expires=1590793041&id=id&accname=guest&checksum=3204085F9555AD9D083799E1F38E3AED}}</ref> ===Americas=== The [[Navajo]] observed the star and named it ''Maʼii Bizòʼ'', the “Coyote Star”. According to legend, Maʼii (Coyote) took part in the naming and placing of the star constellations during the creation of the universe. He placed Canopus directly south, naming it after himself.<ref name="Maryboy">Maryboy, Nancy D. (2004). ''A Guide to Navajo Astronomy.'' Indigenous Education Institute : Bluff, Utah.</ref> The [[Kalapalo]] people of [[Mato Grosso]] state in Brazil saw Canopus and [[Procyon]] as ''Kofongo'' "Duck", with [[Castor (star)|Castor]] and [[Pollux (star)|Pollux]] representing his hands. The asterism's appearance signified the coming of the rainy season and increase in [[manioc]], a food staple fed to guests at feasts.<ref name="basso87">{{cite book|last=Basso|first=Ellen B. |title=In Favor of Deceit: A Study of Tricksters in an Amazonian Society|publisher=University of Arizona Press|location=Tucson, Arizona|date=1987|page=[https://archive.org/details/infavorofdeceits0000bass/page/360 360]|isbn=0816510229|url=https://archive.org/details/infavorofdeceits0000bass|url-access=registration}}</ref> ===Australia=== Canopus is identified as the moiety ancestor ''Waa'' "Crow" to some [[Koori]] people in southeastern Australia.<ref>{{cite book|last=Mudrooroo|title=Aboriginal mythology: an A-Z spanning the history of aboriginal mythology from the earliest legends to the present day|publisher=HarperCollins|location=London|date=1994|page=27|isbn=1-85538-306-3}}</ref> The Boorong people of northwestern Victoria recalled that ''War'' (Canopus) was the brother of ''Warepil'' (Sirius), and that he brought fire from the heavens and introduced it to humanity. His wife was ''Collowgullouric War'' ([[Eta Carinae]]).<ref name=hamacher10>{{cite journal|last1=Hamacher|first1=Duane W. |last2=Frew|first2=David J. |date=2010|title= An Aboriginal Australian Record of the Great Eruption of Eta Carinae|journal=Journal of Astronomical History & Heritage |volume=13|issue=3|pages= 220–34|bibcode=2010JAHH...13..220H|arxiv = 1010.4610 }}</ref> The Pirt-Kopan-noot people of western Victoria tell of ''Waa'' "Crow" falling in love with a queen, ''Gneeanggar'' "Wedge-tailed Eagle" (Sirius) and her six attendants (the Pleiades). His advances spurned, he hears that the women are foraging for grubs and so transforms himself into a grub. When the women dig him out, he changes into a giant and carries her off.<ref>Mudroodoo, p. 55.</ref> The Kulin people know Canopus as ''Lo-an-tuka''.<ref name=hamacher10/> Objects in the sky are also associated with states of being for some tribes; the Wailwun of northern New South Wales know Canopus as ''Wumba'' "deaf", alongside Mars as ''Gumba'' "fat" and Venus as ''Ngindigindoer'' "you are laughing".<ref name="noctuary">{{cite book|last=Johnson|first=Diane|title=Night skies of aboriginal Australia: a noctuary|publisher=University of Sydney|location=Darlington, New South Wales|date=1998|page=[https://archive.org/details/nightskiesofabor0000john/page/84 84]|isbn=1-86451-356-X|url-access=registration|url=https://archive.org/details/nightskiesofabor0000john/page/84}}</ref> Tasmanian aboriginal lore holds that Canopus is ''Dromerdene'', the brother of ''Moinee''; the two fought and fell out of the sky, with ''Dromerdene'' falling into Louisa Bay in southwest Tasmania.<ref name="haynes2000">{{cite book|last=Haynes|first=Ros D.|title= Astronomy and the Dreaming: The Astronomy of the Aboriginal Australians. Astronomy Across Cultures: The History of Non-Western Astronomy|publisher=Kluwer Academic Publishers|date=2000|page=57|doi=10.1007/978-94-011-4179-6_3}}</ref> ===Legacy=== [[File:HMS Glory LOC ggbain.17135.jpg|thumb|right|[[Canopus-class battleship]] HMS Glory]] Canopus appears on the [[flag of Brazil]], symbolising the state of [[Goiás]].<ref>{{cite web |title=Astronomy of the Brazilian Flag |url=https://flagspot.net/flags/br_astro.html |publisher=FOTW Flags Of The World website }}</ref> Two U.S. Navy [[submarine tender]]s have been named after Canopus, the [[USS Canopus (AS-9)|first]] serving from 1922 to 1942 and the [[USS Canopus (AS-34)|second]] serving from 1965 to 1994. The [[Royal Navy]] built nine [[Canopus-class ship of the line|Canopus-class ships of the line]] in the early 19th century, and six {{Sclass|Canopus|battleship|1}}s which entered services between 1899 and 1902. There are at least two mountains named after the star: [[Mount Canopus]] in Antarctica; and Mount Canopus or Canopus Hill in [[Tasmania]], the location of the [[Canopus Hill Observatory|Canopus Hill astronomical observatory]]. {{clear}} <references /> __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ ce29d5314b77a1352c960250ee049531d7f4de06 383 382 2023-07-07T08:51:31Z SpaceMan 2 Replaced content with " Canopus is a bright [[star]] located in the southern constellation of [[Carina]], and is the second brightest star in the night sky after [[Sirius]]. It is a yellowish-white [[supergiant star]] that is approximately 310 [[light-years]] away from [[Earth]] and has a visual magnitude of -0.72. Canopus is a massive star, with an estimated [[mass]] of about 8 to 9 times that of the [[Sun]], and a radius of about 71 times that of the Sun. It is also one of the most lumi..." wikitext text/x-wiki Canopus is a bright [[star]] located in the southern constellation of [[Carina]], and is the second brightest star in the night sky after [[Sirius]]. It is a yellowish-white [[supergiant star]] that is approximately 310 [[light-years]] away from [[Earth]] and has a visual magnitude of -0.72. Canopus is a massive star, with an estimated [[mass]] of about 8 to 9 times that of the [[Sun]], and a radius of about 71 times that of the Sun. It is also one of the most luminous stars in the [[Milky Way]] [[galaxy]], with a luminosity that is estimated to be about 14,000 times that of the Sun. The star's high luminosity and relatively low surface temperature make it appear yellow-white in color. It is also known for its high rotational velocity, with a rotational speed of around 70 km/s at the equator. This high velocity causes the star to bulge at the equator, making it slightly oblate in shape. Canopus is believed to be around 8 to 10 million years old and is nearing the end of its life cycle. It is expected to eventually explode as a [[supernova]], although this is not expected to occur for several million years. Canopus has been an important navigational star for many cultures throughout history, as it is visible from many parts of the world and is one of the brightest stars in the night sky. It was used by ancient navigators to help guide their ships across the ocean, and is still used by some modern-day navigators and [[astronomers]] for similar purposes. In addition to its navigational importance, Canopus has also been the subject of scientific study and observation. Its high luminosity and relatively close distance have made it a useful target for astronomers studying the properties and behavior of stars, and it has been observed by a number of different telescopes and instruments over the years. __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 703ca6cefbc7350bce156c0180a373af4a078ec7 385 383 2023-07-07T08:54:42Z SpaceMan 2 wikitext text/x-wiki [[File:Https://static.miraheze.org/astrobasewiki/2/23/Canopus.jpeg|thumb|center|Canopus]] Canopus is a bright [[star]] located in the southern constellation of [[Carina]], and is the second brightest star in the night sky after [[Sirius]]. It is a yellowish-white [[supergiant star]] that is approximately 310 [[light-years]] away from [[Earth]] and has a visual magnitude of -0.72. Canopus is a massive star, with an estimated [[mass]] of about 8 to 9 times that of the [[Sun]], and a radius of about 71 times that of the Sun. It is also one of the most luminous stars in the [[Milky Way]] [[galaxy]], with a luminosity that is estimated to be about 14,000 times that of the Sun. The star's high luminosity and relatively low surface temperature make it appear yellow-white in color. It is also known for its high rotational velocity, with a rotational speed of around 70 km/s at the equator. This high velocity causes the star to bulge at the equator, making it slightly oblate in shape. Canopus is believed to be around 8 to 10 million years old and is nearing the end of its life cycle. It is expected to eventually explode as a [[supernova]], although this is not expected to occur for several million years. Canopus has been an important navigational star for many cultures throughout history, as it is visible from many parts of the world and is one of the brightest stars in the night sky. It was used by ancient navigators to help guide their ships across the ocean, and is still used by some modern-day navigators and [[astronomers]] for similar purposes. In addition to its navigational importance, Canopus has also been the subject of scientific study and observation. Its high luminosity and relatively close distance have made it a useful target for astronomers studying the properties and behavior of stars, and it has been observed by a number of different telescopes and instruments over the years. __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 75598205b6bd967082034daf9a5fc8d7d378213a 386 385 2023-07-07T08:55:33Z SpaceMan 2 wikitext text/x-wiki [[File:https://static.miraheze.org/astrobasewiki/2/23/Canopus.jpeg|thumb|center|Canopus]] Canopus is a bright [[star]] located in the southern constellation of [[Carina]], and is the second brightest star in the night sky after [[Sirius]]. It is a yellowish-white [[supergiant star]] that is approximately 310 [[light-years]] away from [[Earth]] and has a visual magnitude of -0.72. Canopus is a massive star, with an estimated [[mass]] of about 8 to 9 times that of the [[Sun]], and a radius of about 71 times that of the Sun. It is also one of the most luminous stars in the [[Milky Way]] [[galaxy]], with a luminosity that is estimated to be about 14,000 times that of the Sun. The star's high luminosity and relatively low surface temperature make it appear yellow-white in color. It is also known for its high rotational velocity, with a rotational speed of around 70 km/s at the equator. This high velocity causes the star to bulge at the equator, making it slightly oblate in shape. Canopus is believed to be around 8 to 10 million years old and is nearing the end of its life cycle. It is expected to eventually explode as a [[supernova]], although this is not expected to occur for several million years. Canopus has been an important navigational star for many cultures throughout history, as it is visible from many parts of the world and is one of the brightest stars in the night sky. It was used by ancient navigators to help guide their ships across the ocean, and is still used by some modern-day navigators and [[astronomers]] for similar purposes. In addition to its navigational importance, Canopus has also been the subject of scientific study and observation. Its high luminosity and relatively close distance have made it a useful target for astronomers studying the properties and behavior of stars, and it has been observed by a number of different telescopes and instruments over the years. __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 9495232b3d8b3cb9399c94cf905f3341124ddb96 387 386 2023-07-07T08:58:07Z SpaceMan 2 wikitext text/x-wiki [[File:Canopus.jpeg|thumb|center|Canopus]] Canopus is a bright [[star]] located in the southern constellation of [[Carina]], and is the second brightest star in the night sky after [[Sirius]]. It is a yellowish-white [[supergiant star]] that is approximately 310 [[light-years]] away from [[Earth]] and has a visual magnitude of -0.72. Canopus is a massive star, with an estimated [[mass]] of about 8 to 9 times that of the [[Sun]], and a radius of about 71 times that of the Sun. It is also one of the most luminous stars in the [[Milky Way]] [[galaxy]], with a luminosity that is estimated to be about 14,000 times that of the Sun. The star's high luminosity and relatively low surface temperature make it appear yellow-white in color. It is also known for its high rotational velocity, with a rotational speed of around 70 km/s at the equator. This high velocity causes the star to bulge at the equator, making it slightly oblate in shape. Canopus is believed to be around 8 to 10 million years old and is nearing the end of its life cycle. It is expected to eventually explode as a [[supernova]], although this is not expected to occur for several million years. Canopus has been an important navigational star for many cultures throughout history, as it is visible from many parts of the world and is one of the brightest stars in the night sky. It was used by ancient navigators to help guide their ships across the ocean, and is still used by some modern-day navigators and [[astronomers]] for similar purposes. In addition to its navigational importance, Canopus has also been the subject of scientific study and observation. Its high luminosity and relatively close distance have made it a useful target for astronomers studying the properties and behavior of stars, and it has been observed by a number of different telescopes and instruments over the years. __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 619b26c2328f4a75413af5054862e410f6d3a5a1 File:Canopus.jpeg 6 175 384 2023-07-07T08:53:22Z SpaceMan 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Earth 0 176 388 2023-07-07T09:19:43Z SpaceMan 2 Created page with "{{Short description|Third planet from the Sun}} | name = Earth | alt_names = Prithvi, Gaia , Terra , the world, the globe , Mother Earth" wikitext text/x-wiki {{Short description|Third planet from the Sun}} | name = Earth | alt_names = Prithvi, Gaia , Terra , the world, the globe , Mother Earth 675aa6e01be6c14a2756643b3c0fc461d100f354 389 388 2023-07-07T10:30:48Z SpaceMan 2 wikitext text/x-wiki Earth is the third [[planet]] from the [[Sun]] and the only place known in the [[universe]] where [[life]] has originated and found habitability. Earth is the only planet known to sustain liquid surface water, with ocean water extending over 70.8% of the planet, making it an ocean world. Most other water is retained in Earth's polar regions, with large sheets of ice covering ocean and land, dwarfing Earth's groundwater, lakes, rivers and atmospheric water. The other 29.2% of the Earth's surface is land, consisting of continents and islands, and is widely covered by vegetation. Below the planet's surface lies the crust, consisting of several slowly moving tectonic plates, which interact to produce mountain ranges, volcanoes, and earthquakes. Inside the Earth's crust is a liquid outer core that generates the [[magnetosphere]], deflecting most of the destructive [[solar winds]] and cosmic radiation. Earth is rounded into an ellipsoid with a circumference of about 40,000 km. It is the densest planet in the Solar System. Of the four rocky planets, it is the largest and most massive. Earth is about eight light-minutes away from the Sun and orbits it, taking a year (about 365.25 days) to complete one revolution. The Earth rotates around its own axis in slightly less than a day (in about 23 hours and 56 minutes). The Earth's axis of rotation is tilted with respect to the perpendicular to its orbital plane around the [[Sun]], producing seasons. Earth is orbited by one permanent natural [[satellite]], the Moon, which orbits Earth at 384,400 km (1.28 light seconds) and is roughly a quarter as wide as Earth. Through tidal locking, the [[Moon]] always faces the Earth with the same side, which causes tides, stabilizes Earth's axis, and gradually slows its rotation. Earth, like most other bodies in the Solar System, formed 4.5 billion years ago from gas in the early [[Solar System]]. 667cc7d96af9036fb33a1310b1a6b3b8991dee99 Galaxy 0 177 390 2023-07-07T15:03:15Z SpaceMan 2 Created page with "A galaxy is a massive collection of [[stars]], gas, dust, and other celestial objects bound together by [[gravity]]. Galaxies come in a variety of shapes, sizes, and colors, and can range from small, irregularly shaped dwarf galaxies to large, spiral-shaped galaxies containing billions of stars. The [[Milky Way]], the galaxy in which [[Earth]] is located, is estimated to contain around 100 billion [[stars]], as well as a supermassive [[black hole]] at its center. The Mi..." wikitext text/x-wiki A galaxy is a massive collection of [[stars]], gas, dust, and other celestial objects bound together by [[gravity]]. Galaxies come in a variety of shapes, sizes, and colors, and can range from small, irregularly shaped dwarf galaxies to large, spiral-shaped galaxies containing billions of stars. The [[Milky Way]], the galaxy in which [[Earth]] is located, is estimated to contain around 100 billion [[stars]], as well as a supermassive [[black hole]] at its center. The Milky Way is a spiral galaxy, with arms of gas, dust, and stars spiraling out from the central bulge. Galaxies are classified into several different types based on their shapes. Spiral galaxies, like the Milky Way, have a central bulge and spiral arms that extend outwards. Elliptical galaxies, on the other hand, are shaped like ellipsoids and have no discernible structure. Irregular galaxies have no particular shape or structure and are often the result of gravitational interactions with other galaxies. Galaxies are also classified based on their color, which is determined by the types of stars and other objects within them. Blue galaxies contain young, hot stars, while red galaxies contain older, cooler stars. Green galaxies are a mixture of both young and old stars. Galaxies are thought to have formed shortly after the [[Big Bang]], when the [[universe]] was still in its infancy. Over time, galaxies have evolved and changed as stars are born and die, as well as through gravitational interactions with other galaxies. Despite their enormous size, galaxies are still subject to the laws of physics and are affected by a range of phenomena, including black holes, [[supernova]], and [[dark matter]]. Scientists continue to study galaxies to better understand their origins, evolution, and the intricate web of interactions that governs their behavior. The study of galaxies has also led to a number of important discoveries and advancements in our understanding of the universe. For example, the discovery of the [[cosmic microwave background radiation]], which is believed to be leftover radiation from the Big Bang, was a crucial piece of evidence in support of the Big Bang theory. == Summary == In summary, galaxies are massive collections of stars, gas, dust, and other celestial objects that are bound together by gravity. They come in a variety of shapes, sizes, and colors, and have played a critical role in our understanding of the universe and its origins. As scientists continue to study galaxies, we can expect to gain even greater insight into the workings of the universe and our place within it. 5e7cae4e4abd8178059b6376838ef9cffb0ae0ce 391 390 2023-07-07T15:03:50Z SpaceMan 2 Protected "[[Galaxy]]": Edit warring ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) wikitext text/x-wiki A galaxy is a massive collection of [[stars]], gas, dust, and other celestial objects bound together by [[gravity]]. Galaxies come in a variety of shapes, sizes, and colors, and can range from small, irregularly shaped dwarf galaxies to large, spiral-shaped galaxies containing billions of stars. The [[Milky Way]], the galaxy in which [[Earth]] is located, is estimated to contain around 100 billion [[stars]], as well as a supermassive [[black hole]] at its center. The Milky Way is a spiral galaxy, with arms of gas, dust, and stars spiraling out from the central bulge. Galaxies are classified into several different types based on their shapes. Spiral galaxies, like the Milky Way, have a central bulge and spiral arms that extend outwards. Elliptical galaxies, on the other hand, are shaped like ellipsoids and have no discernible structure. Irregular galaxies have no particular shape or structure and are often the result of gravitational interactions with other galaxies. Galaxies are also classified based on their color, which is determined by the types of stars and other objects within them. Blue galaxies contain young, hot stars, while red galaxies contain older, cooler stars. Green galaxies are a mixture of both young and old stars. Galaxies are thought to have formed shortly after the [[Big Bang]], when the [[universe]] was still in its infancy. Over time, galaxies have evolved and changed as stars are born and die, as well as through gravitational interactions with other galaxies. Despite their enormous size, galaxies are still subject to the laws of physics and are affected by a range of phenomena, including black holes, [[supernova]], and [[dark matter]]. Scientists continue to study galaxies to better understand their origins, evolution, and the intricate web of interactions that governs their behavior. The study of galaxies has also led to a number of important discoveries and advancements in our understanding of the universe. For example, the discovery of the [[cosmic microwave background radiation]], which is believed to be leftover radiation from the Big Bang, was a crucial piece of evidence in support of the Big Bang theory. == Summary == In summary, galaxies are massive collections of stars, gas, dust, and other celestial objects that are bound together by gravity. They come in a variety of shapes, sizes, and colors, and have played a critical role in our understanding of the universe and its origins. As scientists continue to study galaxies, we can expect to gain even greater insight into the workings of the universe and our place within it. 5e7cae4e4abd8178059b6376838ef9cffb0ae0ce 392 391 2023-07-07T15:10:35Z SpaceMan 2 wikitext text/x-wiki [https://cdn.britannica.com/05/94905-004-1AFF8DFF/Whirlpool-Galaxy-NGC-5195-Sc.jpg?s=1500x700&q=85 Galaxy] A galaxy is a massive collection of [[stars]], gas, dust, and other celestial objects bound together by [[gravity]]. Galaxies come in a variety of shapes, sizes, and colors, and can range from small, irregularly shaped dwarf galaxies to large, spiral-shaped galaxies containing billions of stars. The [[Milky Way]], the galaxy in which [[Earth]] is located, is estimated to contain around 100 billion [[stars]], as well as a supermassive [[black hole]] at its center. The Milky Way is a spiral galaxy, with arms of gas, dust, and stars spiraling out from the central bulge. Galaxies are classified into several different types based on their shapes. Spiral galaxies, like the Milky Way, have a central bulge and spiral arms that extend outwards. Elliptical galaxies, on the other hand, are shaped like ellipsoids and have no discernible structure. Irregular galaxies have no particular shape or structure and are often the result of gravitational interactions with other galaxies. Galaxies are also classified based on their color, which is determined by the types of stars and other objects within them. Blue galaxies contain young, hot stars, while red galaxies contain older, cooler stars. Green galaxies are a mixture of both young and old stars. Galaxies are thought to have formed shortly after the [[Big Bang]], when the [[universe]] was still in its infancy. Over time, galaxies have evolved and changed as stars are born and die, as well as through gravitational interactions with other galaxies. Despite their enormous size, galaxies are still subject to the laws of physics and are affected by a range of phenomena, including black holes, [[supernova]], and [[dark matter]]. Scientists continue to study galaxies to better understand their origins, evolution, and the intricate web of interactions that governs their behavior. The study of galaxies has also led to a number of important discoveries and advancements in our understanding of the universe. For example, the discovery of the [[cosmic microwave background radiation]], which is believed to be leftover radiation from the Big Bang, was a crucial piece of evidence in support of the Big Bang theory. ==Summary== In summary, galaxies are massive collections of stars, gas, dust, and other celestial objects that are bound together by gravity. They come in a variety of shapes, sizes, and colors, and have played a critical role in our understanding of the universe and its origins. As scientists continue to study galaxies, we can expect to gain even greater insight into the workings of the universe and our place within it. <ref>https://www.britannica.com/science/galaxy</ref> <ref>https://en.m.wikipedia.org/wiki/Galaxy</ref> <references /> [[Category:Astronomy]] __FORCETOC__ __NOEDITSECTION__ __INDEX__ __NEWSECTIONLINK__ cd1f4710f55c912fab06337312c51b42ad52108b 394 392 2023-07-07T15:14:22Z SpaceMan 2 wikitext text/x-wiki [[File:NGC 4414 (NASA-med).jpg|thumb|center|NGC 4414]] A galaxy is a massive collection of [[stars]], gas, dust, and other celestial objects bound together by [[gravity]]. Galaxies come in a variety of shapes, sizes, and colors, and can range from small, irregularly shaped dwarf galaxies to large, spiral-shaped galaxies containing billions of stars. The [[Milky Way]], the galaxy in which [[Earth]] is located, is estimated to contain around 100 billion [[stars]], as well as a supermassive [[black hole]] at its center. The Milky Way is a spiral galaxy, with arms of gas, dust, and stars spiraling out from the central bulge. Galaxies are classified into several different types based on their shapes. Spiral galaxies, like the Milky Way, have a central bulge and spiral arms that extend outwards. Elliptical galaxies, on the other hand, are shaped like ellipsoids and have no discernible structure. Irregular galaxies have no particular shape or structure and are often the result of gravitational interactions with other galaxies. Galaxies are also classified based on their color, which is determined by the types of stars and other objects within them. Blue galaxies contain young, hot stars, while red galaxies contain older, cooler stars. Green galaxies are a mixture of both young and old stars. Galaxies are thought to have formed shortly after the [[Big Bang]], when the [[universe]] was still in its infancy. Over time, galaxies have evolved and changed as stars are born and die, as well as through gravitational interactions with other galaxies. Despite their enormous size, galaxies are still subject to the laws of physics and are affected by a range of phenomena, including black holes, [[supernova]], and [[dark matter]]. Scientists continue to study galaxies to better understand their origins, evolution, and the intricate web of interactions that governs their behavior. The study of galaxies has also led to a number of important discoveries and advancements in our understanding of the universe. For example, the discovery of the [[cosmic microwave background radiation]], which is believed to be leftover radiation from the Big Bang, was a crucial piece of evidence in support of the Big Bang theory. ==Summary== In summary, galaxies are massive collections of stars, gas, dust, and other celestial objects that are bound together by gravity. They come in a variety of shapes, sizes, and colors, and have played a critical role in our understanding of the universe and its origins. As scientists continue to study galaxies, we can expect to gain even greater insight into the workings of the universe and our place within it. <ref>https://www.britannica.com/science/galaxy</ref> <ref>https://en.m.wikipedia.org/wiki/Galaxy</ref> <references /> [[Category:Astronomy]] __FORCETOC__ __NOEDITSECTION__ __INDEX__ __NEWSECTIONLINK__ 4daa84342ae05205f847fcba53911badd41129e6 File:NGC4414.jpeg 6 178 393 2023-07-07T15:12:33Z SpaceMan 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VY Canis Major 0 31 395 70 2023-07-07T15:21:17Z SpaceMan 2 /* Definition */ wikitext text/x-wiki [[File:VY Canis Major.jpg|thumb|VY Canis Major]] ==Definition== VY Canis Majoris or VY CMa is a red Hypergiant [[star]]. It is located in the constellation [[Canis Major]]. It is one of the largest and brightest red hypergiants observed so far. It has a diameter of 1800 solar radii. This star emits energy very quickly and therefore, only exists for a few million years. It is estimated to be 4900 light years away from Earth. This star shows periodic light changes that last for approximately 2200 days. ==The crimson star== The first known recorded observation of VY Canis Majoris is in the star catalogue of Jérôme Lalande, who recorded it on 7th March, 1801. Since 1847, VY CMa has been known to be a crimson star. Originally, University of Minnesota Professor Roberta M. Humphreys approximated that the radius of VY CMa is 1800-2100 times that of the Sun. This would make it the largest known star based on its radius. ==Surface== This star also illustrates the conceptual problem of defining the "surface" of very large stars. This is very important for multiple reasons, including determining its radius and thus its size. It is a hundred thousand times less dense than the atmosphere of Earth (air) at sea level. Its average density is 0.000005 to 0.000010 kg per m³. Additionally, the star is constantly losing mass at an astounding rate. The boundary of such a star is usually defined by its "[[Rosseland Radius]]", which is based on its opaqueness to light. 4418fb3b986edba3dcf05f3740e75035c9699370 MediaWiki:Citizen-footer-tagline 8 179 397 2023-07-07T17:57:49Z SpaceMan 2 Created page with "This Is ASTROBASE created by SpaceMan." wikitext text/x-wiki This Is ASTROBASE created by SpaceMan. 5d6989ec599e5f7d1020048182d29a2272c948b1 User:SpaceMan/sandbox 2 180 398 2023-07-09T09:25:14Z SpaceMan 2 Created page with "{{Infobox | title = Sun }}" wikitext text/x-wiki {{Infobox | title = Sun }} 5c49d5832a8ca4460f3b6b0090da8196a41cca02 File:Web 1689012928768 1689012934764.jpg 6 181 400 2023-07-12T19:01:46Z SpaceMan 2 wikitext text/x-wiki Astronomy picture 1c770de604435d50768248a49185707664338fc0 Universe 0 182 401 2023-07-12T19:03:30Z SpaceMan 2 the universe is a vast and complex system of galaxies, stars, planets, and other celestial bodies, estimated to be approximately 13.8 billion years old and spanning an estimated 93 billion light-years in diameter. It began with the Big Bang and is constantly expanding, with dark matter and dark energy making up the majority of its mass and energy. Through ongoing scientific research, we continue to gain a better understanding of the universe and its properties. wikitext text/x-wiki [[File:Web 1689012928768 1689012934764.jpg|thumb|center]] ==Definition== The universe is a vast and complex system of [[galaxies]], [[stars]], [[planets]], and other celestial bodies. It is estimated to be approximately 13.8 billion years old and spans an estimated 93 billion [[light-years]] in diameter. The universe is believed to have begun with a massive explosion called the [[Big Bang]], which occurred approximately 13.8 billion years ago. At the time of the Big Bang, the universe was extremely hot and dense, and rapidly expanded and cooled over time. The universe is composed of various types of matter and energy, including [[dark matter]] and [[dark energy]], which are not directly observable but are believed to make up the majority of the universe's mass and energy. Ordinary matter, which includes atoms and molecules, makes up only a small fraction of the universe. The observable universe contains an estimated 2 trillion galaxies, each containing billions of stars. The [[Milky Way]] galaxy, which contains our [[solar system]], is estimated to contain approximately 100 billion stars. The universe also contains various types of celestial bodies, including planets, moons, [[asteroid]], and [[comet]]. The universe is constantly expanding, and the rate of expansion is accelerating. This expansion is believed to be driven by dark energy, which is causing the universe to expand at an increasing rate over time. The study of the universe is a complex and ongoing field of scientific research. Astronomers and cosmologists use various tools and techniques, including telescopes, satellites, and computer simulations, to study the universe and its properties. Through these efforts, scientists have gained a better understanding of the origins, structure, and evolution of the universe, and continue to make new discoveries and advances in our understanding of the cosmos. ==Summary== In summary, the universe is a vast and complex system of galaxies, stars, planets, and other celestial bodies, estimated to be approximately 13.8 billion years old and spanning an estimated 93 billion light-years in diameter. It began with the Big Bang and is constantly expanding, with dark matter and dark energy making up the majority of its mass and energy. Through ongoing scientific research, we continue to gain a better understanding of the universe and its properties. ---- <ref>https://en.m.wikipedia.org/wiki/Universe</ref> __FORCETOC__ 137016315513e49cbadda37cabd5613da238b038 402 401 2023-07-12T19:05:59Z SpaceMan 2 wikitext text/x-wiki [[File:Web 1689012928768 1689012934764.jpg|thumb|center]] ==Definition== The universe is a vast and complex system of [[galaxies]], [[stars]], [[planets]], and other celestial bodies. It is estimated to be approximately 13.8 billion years old and spans an estimated 93 billion [[light-years]] in diameter. The universe is believed to have begun with a massive explosion called the [[Big Bang]], which occurred approximately 13.8 billion years ago. At the time of the Big Bang, the universe was extremely hot and dense, and rapidly expanded and cooled over time. The universe is composed of various types of matter and energy, including [[dark matter]] and [[dark energy]], which are not directly observable but are believed to make up the majority of the universe's mass and energy. Ordinary matter, which includes atoms and molecules, makes up only a small fraction of the universe. The observable universe contains an estimated 2 trillion galaxies, each containing billions of stars. The [[Milky Way]] galaxy, which contains our [[solar system]], is estimated to contain approximately 100 billion stars. The universe also contains various types of celestial bodies, including planets, moons, [[asteroid]], and [[comet]]. The universe is constantly expanding, and the rate of expansion is accelerating. This expansion is believed to be driven by dark energy, which is causing the universe to expand at an increasing rate over time. The study of the universe is a complex and ongoing field of scientific research. Astronomers and cosmologists use various tools and techniques, including telescopes, satellites, and computer simulations, to study the universe and its properties. Through these efforts, scientists have gained a better understanding of the origins, structure, and evolution of the universe, and continue to make new discoveries and advances in our understanding of the cosmos. ==Summary== In summary, the universe is a vast and complex system of galaxies, stars, planets, and other celestial bodies, estimated to be approximately 13.8 billion years old and spanning an estimated 93 billion light-years in diameter. It began with the Big Bang and is constantly expanding, with dark matter and dark energy making up the majority of its mass and energy. Through ongoing scientific research, we continue to gain a better understanding of the universe and its properties. ---- <ref>https://en.m.wikipedia.org/wiki/Universe</ref> __FORCETOC__ __INDEX__ 17dd9ea36e4bca996fee77f10b3884f72f52171b Main Page 0 1 404 396 2023-07-13T07:08:47Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase}} '''Welcome to {{SITENAME}}!'''<br> Astronomy is study of everything outside Earth which includes Star , planets , nebulas , supernovas, etc . It uses mathematics, physics, and chemistry in order to explain their origin and evolution. '''{{SITENAME}}''' is a wiki dedicated to astronomy . <br> '''Note : Wiki is in development''' '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] <!-- Disclaimer: AI generated text are also being used , so if you find any mistake kindly reach The administrator --> [[File:Logospaceman.png|alt=Logo|thumb]] [[Category:Main]] __NOEDITSECTION__ __INDEX__ __FORCETOC__ __NEWSECTIONLINK__ {{DEFAULTSORT:home}} cd6c380854ee7fff8e8527bd10be25b477e8f16a 408 404 2023-07-13T07:37:37Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase}} '''Welcome to {{SITENAME}}!'''<br> [[Astronomy]] is the scientific discipline that studies the celestial objects and phenomena beyond the [[Earth's]] atmosphere. It encompasses a wide range of topics, including the properties, behavior, and evolution of [[stars]], [[planets]], [[galaxies]], and the universe as a whole. Astronomers use a variety of tools to study the cosmos, including telescopes, satellites, and computer simulations. [[Astronomy]] has been practiced for thousands of years and has contributed significantly to our understanding of the [[universe]], including the discovery of [[exoplanets]], the nature of [[black holes]], and the [[Big Bang]] theory. Today, astronomy continues to be a fascinating and active area of research, with astronomers exploring new ways to unlock the mysteries of the [[cosmos]]. '''{{SITENAME}}''' is a wiki dedicated to astronomy . <br> '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] <!-- Disclaimer: AI generated text are also being used , so if you find any mistake kindly reach The administrator --> [[File:Logospaceman.png|alt=Logo|thumb]] [[Category:Main]] __NOEDITSECTION__ __INDEX__ __FORCETOC__ __NEWSECTIONLINK__ {{DEFAULTSORT:home}} d2115b616de9e1a282a24f938ce190cc1c04ad3b 411 408 2023-07-13T17:36:09Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astrobase}} '''Welcome to {{SITENAME}}!'''<br> [[Astronomy]] is the scientific discipline that studies the celestial objects and phenomena beyond the [[Earth's]] atmosphere. It encompasses a wide range of topics, including the properties, behavior, and evolution of [[stars]], [[planets]], [[galaxies]], and the universe as a whole. Astronomers use a variety of tools to study the cosmos, including telescopes, satellites, and computer simulations. [[Astronomy]] has been practiced for thousands of years and has contributed significantly to our understanding of the [[universe]], including the discovery of [[exoplanets]], the nature of [[black holes]], and the [[Big Bang]] theory. Today, astronomy continues to be a fascinating and active area of research, with astronomers exploring new ways to unlock the mysteries of the [[cosmos]]. '''{{SITENAME}}''' is a wiki dedicated to astronomy . <br> '''Quick List'''<br> [[Special:AllPages ]]<br> [[Special:ListUsers]]<br> [[Special:WantedPages]] '''Astronomy Database Portal'''<br> [https://astrobase.miraheze.org/wiki/Astronomy_Database_portal Astronomy Database Portal] <br> '''''Note: Some page are also using AI Generated Content.''''' [[Category:Main]] __NOEDITSECTION__ __INDEX__ __FORCETOC__ __NEWSECTIONLINK__ d0c1d6f5e0498f6a6a09c7cd1219e21d76c70862 File:CMB Timeline.jpg 6 183 405 2023-07-13T07:20:52Z SpaceMan 2 wikitext text/x-wiki Cmb timeline 4b42ef4495959f832257ff2254478fafd78f6849 Big Bang 0 184 406 2023-07-13T07:23:32Z SpaceMan 2 Created page with "==Definition== The Big Bang theory is the prevailing scientific explanation for the origin and evolution of the [[universe]]. According to this theory, the universe began as a [[singularity]], a point of infinite density and temperature, approximately 13.8 billion years ago. [[File:CMB Timeline.jpg|alt=CMB Timeline |center|frameless|CMB timeline ]] At the time of the Big Bang, the universe was extremely hot and dense, and rapidly expanded and cooled over time. As it ex..." wikitext text/x-wiki ==Definition== The Big Bang theory is the prevailing scientific explanation for the origin and evolution of the [[universe]]. According to this theory, the universe began as a [[singularity]], a point of infinite density and temperature, approximately 13.8 billion years ago. [[File:CMB Timeline.jpg|alt=CMB Timeline |center|frameless|CMB timeline ]] At the time of the Big Bang, the universe was extremely hot and dense, and rapidly expanded and cooled over time. As it expanded, it cooled, allowing subatomic particles to form, including [[protons]], [[neutrons]], and [[electrons]]. During the first few minutes after the Big Bang, a process called [[nucleosynthesis]] occurred, in which atomic nuclei were formed through the fusion of protons and neutrons. This process created the light elements hydrogen, helium, and lithium, which were later used to form the first [[stars]] and [[galaxy]]. Over time, the expanding universe continued to cool, allowing atoms to form and the universe to become transparent to light. This moment, known as the [[cosmic microwave background radiation]], occurred approximately 380,000 years after the Big Bang and is still detectable today. The Big Bang theory is supported by a variety of evidence, including observations of the cosmic microwave background radiation, the abundance of light elements in the universe, and the large-scale structure of the universe. While the Big Bang theory is the prevailing scientific explanation for the origin and evolution of the universe, it is not without its limitations and areas of debate. For example, the theory does not yet provide a complete explanation for the formation of galaxies and other large structures in the universe, or the nature of [[dark matter]] and [[dark energy]], which are believed to make up the majority of the universe's mass and [[energy]]. Despite these limitations, the Big Bang theory remains a cornerstone of modern cosmology, providing a framework for understanding the history and evolution of the universe. ==What are some current areas of research related to the Big Bang theory?== There are several current areas of research related to the Big Bang theory, which continue to expand our understanding of the origins and evolution of the universe. Some of these areas include: 1. Inflationary cosmology: Inflationary cosmology is a theory that suggests that the universe underwent a brief period of exponential expansion in the moments following the Big Bang. This theory helps to explain certain features of the cosmic microwave background radiation, such as its uniformity and lack of large-scale structure. 2. Dark matter and dark energy: Dark matter and dark energy are believed to make up the majority of the universe's mass and energy, but their exact nature is still not well understood. Researchers are continuing to study the properties of dark matter and dark energy, in order to better understand their role in the evolution of the universe. 3. Cosmic microwave background radiation: The cosmic microwave background radiation is the afterglow of the Big Bang, and provides a wealth of information about the early universe. Researchers are studying the cosmic microwave background radiation in order to learn more about the conditions that existed in the universe shortly after the Big Bang. 4. Large-scale structure of the universe: The large-scale structure of the universe, including the distribution of galaxies and other cosmic structures, provides important clues about the evolution of the universe. Researchers are using large-scale surveys and computer simulations to study the structure of the universe and its origins. 5. Neutrino physics: Neutrinos are subatomic particles that are produced in the early universe, and can provide important information about the conditions that existed shortly after the Big Bang. Researchers are studying the properties of neutrinos in order to better understand the early universe and its evolution. Overall, these areas of research and others related to the Big Bang theory are helping to expand our understanding of the universe and its origins, and may lead toThe Big Bang theory is the prevailing scientific explanation for the origin and evolution of the [[universe]]. According to this theory, the universe began as a [[singularity]], a point of infinite density and temperature, approximately 13.8 billion years ago. 53ad2aa0e7755cfcacd49e66dfdcc7fac38ee4b8 407 406 2023-07-13T07:33:15Z SpaceMan 2 wikitext text/x-wiki ==Definition== The Big Bang theory is the prevailing scientific explanation for the origin and evolution of the [[universe]]. According to this theory, the universe began as a [[singularity]], a point of infinite density and temperature, approximately 13.8 billion years ago. [[File:CMB Timeline.jpg|alt=CMB Timeline |center|frameless|CMB timeline ]] At the time of the Big Bang, the universe was extremely hot and dense, and rapidly expanded and cooled over time. As it expanded, it cooled, allowing subatomic particles to form, including [[protons]], [[neutrons]], and [[electrons]]. During the first few minutes after the Big Bang, a process called [[nucleosynthesis]] occurred, in which atomic nuclei were formed through the fusion of protons and neutrons. This process created the light elements hydrogen, helium, and lithium, which were later used to form the first [[stars]] and [[galaxy]]. Over time, the expanding universe continued to cool, allowing atoms to form and the universe to become transparent to light. This moment, known as the [[cosmic microwave background radiation]], occurred approximately 380,000 years after the Big Bang and is still detectable today. The Big Bang theory is supported by a variety of evidence, including observations of the cosmic microwave background radiation, the abundance of light elements in the universe, and the large-scale structure of the universe. While the Big Bang theory is the prevailing scientific explanation for the origin and evolution of the universe, it is not without its limitations and areas of debate. For example, the theory does not yet provide a complete explanation for the formation of galaxies and other large structures in the universe, or the nature of [[dark matter]] and [[dark energy]], which are believed to make up the majority of the universe's mass and [[energy]]. Despite these limitations, the Big Bang theory remains a cornerstone of modern cosmology, providing a framework for understanding the history and evolution of the universe. ==What are some current areas of research related to the Big Bang theory?== There are several current areas of research related to the Big Bang theory, which continue to expand our understanding of the origins and evolution of the universe. Some of these areas include: 1. Inflationary cosmology: Inflationary cosmology is a theory that suggests that the universe underwent a brief period of exponential expansion in the moments following the Big Bang. This theory helps to explain certain features of the cosmic microwave background radiation, such as its uniformity and lack of large-scale structure. 2. Dark matter and dark energy: Dark matter and dark energy are believed to make up the majority of the universe's mass and energy, but their exact nature is still not well understood. Researchers are continuing to study the properties of dark matter and dark energy, in order to better understand their role in the evolution of the universe. 3. Cosmic microwave background radiation: The cosmic microwave background radiation is the afterglow of the Big Bang, and provides a wealth of information about the early universe. Researchers are studying the cosmic microwave background radiation in order to learn more about the conditions that existed in the universe shortly after the Big Bang. 4. Large-scale structure of the universe: The large-scale structure of the universe, including the distribution of galaxies and other cosmic structures, provides important clues about the evolution of the universe. Researchers are using large-scale surveys and computer simulations to study the structure of the universe and its origins. 5. Neutrino physics: Neutrinos are subatomic particles that are produced in the early universe, and can provide important information about the conditions that existed shortly after the Big Bang. Researchers are studying the properties of neutrinos in order to better understand the early universe and its evolution. Overall, these areas of research and others related to the Big Bang theory are helping to expand our understanding of the universe and its origins, and may lead toThe Big Bang theory is the prevailing scientific explanation for the origin and evolution of the [[universe]]. According to this theory, the universe began as a [[singularity]], a point of infinite density and temperature, approximately 13.8 billion years ago. [[Category:Astronomy]] {{DEFAULTSORT:BigBang}} __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ c32ce964aa998a5991dd7ab454052672649e5275 425 407 2023-07-13T18:24:24Z SpaceMan 2 /* Definition */ wikitext text/x-wiki The Big Bang theory is the prevailing scientific explanation for the origin and evolution of the [[universe]]. According to this theory, the universe began as a [[singularity]], a point of infinite density and temperature, approximately 13.8 billion years ago. [[File:CMB Timeline.jpg|alt=CMB Timeline |center|frameless|CMB timeline ]] At the time of the Big Bang, the universe was extremely hot and dense, and rapidly expanded and cooled over time. As it expanded, it cooled, allowing subatomic particles to form, including [[protons]], [[neutrons]], and [[electrons]]. During the first few minutes after the Big Bang, a process called [[nucleosynthesis]] occurred, in which atomic nuclei were formed through the fusion of protons and neutrons. This process created the light elements hydrogen, helium, and lithium, which were later used to form the first [[stars]] and [[galaxy]]. Over time, the expanding universe continued to cool, allowing atoms to form and the universe to become transparent to light. This moment, known as the [[cosmic microwave background radiation]], occurred approximately 380,000 years after the Big Bang and is still detectable today. The Big Bang theory is supported by a variety of evidence, including observations of the cosmic microwave background radiation, the abundance of light elements in the universe, and the large-scale structure of the universe. While the Big Bang theory is the prevailing scientific explanation for the origin and evolution of the universe, it is not without its limitations and areas of debate. For example, the theory does not yet provide a complete explanation for the formation of galaxies and other large structures in the universe, or the nature of [[dark matter]] and [[dark energy]], which are believed to make up the majority of the universe's mass and [[energy]]. Despite these limitations, the Big Bang theory remains a cornerstone of modern cosmology, providing a framework for understanding the history and evolution of the universe. ==What are some current areas of research related to the Big Bang theory?== There are several current areas of research related to the Big Bang theory, which continue to expand our understanding of the origins and evolution of the universe. Some of these areas include: 1. Inflationary cosmology: Inflationary cosmology is a theory that suggests that the universe underwent a brief period of exponential expansion in the moments following the Big Bang. This theory helps to explain certain features of the cosmic microwave background radiation, such as its uniformity and lack of large-scale structure. 2. Dark matter and dark energy: Dark matter and dark energy are believed to make up the majority of the universe's mass and energy, but their exact nature is still not well understood. Researchers are continuing to study the properties of dark matter and dark energy, in order to better understand their role in the evolution of the universe. 3. Cosmic microwave background radiation: The cosmic microwave background radiation is the afterglow of the Big Bang, and provides a wealth of information about the early universe. Researchers are studying the cosmic microwave background radiation in order to learn more about the conditions that existed in the universe shortly after the Big Bang. 4. Large-scale structure of the universe: The large-scale structure of the universe, including the distribution of galaxies and other cosmic structures, provides important clues about the evolution of the universe. Researchers are using large-scale surveys and computer simulations to study the structure of the universe and its origins. 5. Neutrino physics: Neutrinos are subatomic particles that are produced in the early universe, and can provide important information about the conditions that existed shortly after the Big Bang. Researchers are studying the properties of neutrinos in order to better understand the early universe and its evolution. Overall, these areas of research and others related to the Big Bang theory are helping to expand our understanding of the universe and its origins, and may lead toThe Big Bang theory is the prevailing scientific explanation for the origin and evolution of the [[universe]]. According to this theory, the universe began as a [[singularity]], a point of infinite density and temperature, approximately 13.8 billion years ago. [[Category:Astronomy]] {{DEFAULTSORT:BigBang}} __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 5713f1a8b30f22a4f9347a14dfc4d61d44440b58 Earth's 0 185 409 2023-07-13T08:26:10Z SpaceMan 2 Redirected page to [[Earth]] wikitext text/x-wiki #REDIRECT [[Earth]] __STATICREDIRECT__ 45c3bc0208c3e61fe74305e509c5e572012de22b Galaxies 0 186 410 2023-07-13T08:27:31Z SpaceMan 2 Redirected page to [[Galaxy]] wikitext text/x-wiki #REDIRECT [[Galaxy ]] ee01d9683043e673e7758285f093d85f76b8a5e2 Astronomy Database portal 0 30 412 88 2023-07-13T17:37:10Z SpaceMan 2 /* Astronomy Data Portal */ wikitext text/x-wiki This is Astronomy Data Portal (ADP). Note: following content may be taken from verious sources. ==Star== {| class="wikitable" |+STAR |- |[https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major] |- |[https://astrobase.miraheze.org/wiki/Sirius Sirius] |- |[https://astrobase.miraheze.org/wiki/Canopus Canopus] |} cbce893de517dde6ba48f408a4b4371388cb135e 413 412 2023-07-13T17:39:23Z SpaceMan 2 /* Star */ wikitext text/x-wiki This is Astronomy Data Portal (ADP). Note: following content may be taken from verious sources. ==Star== {| class="wikitable" |+STAR |- |[https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major] |- |[https://astrobase.miraheze.org/wiki/Sirius Sirius] |- |[https://astrobase.miraheze.org/wiki/Canopus Canopus] |- | [https://astrobase.miraheze.org/wiki/Sun Sun] |} 0c004b7ac02e1eb4d43995898bc02935916dba58 414 413 2023-07-13T17:40:44Z SpaceMan 2 wikitext text/x-wiki {{DISPLAYTITLE:Astronomy Data portal}} This is Astronomy Data Portal (ADP). Note: following content may be taken from verious sources. ==Star== {| class="wikitable" |+STAR |- |[https://astrobase.miraheze.org/wiki/VY_Canis_Major VY Canis Major] |- |[https://astrobase.miraheze.org/wiki/Sirius Sirius] |- |[https://astrobase.miraheze.org/wiki/Canopus Canopus] |- | [https://astrobase.miraheze.org/wiki/Sun Sun] |} [[Category:Main]] [[Category:Astronomy]] {{DEFAULTSORT:Astronomy_Data_portal}} __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ c0fc8918e99f8ca7954333f9211a831a61026522 Cosmos 0 187 415 2023-07-13T17:42:44Z SpaceMan 2 Redirected page to [[Universe]] wikitext text/x-wiki #REDIRECT [[Universe ]] __INDEX__ __NEWSECTIONLINK__ c65372757cd62073377bedc18a9cdd6d27294a66 Universe 0 182 416 402 2023-07-13T17:43:19Z SpaceMan 2 /* Definition */ wikitext text/x-wiki [[File:Web 1689012928768 1689012934764.jpg|thumb|center]] The universe is a vast and complex system of [[galaxies]], [[stars]], [[planets]], and other celestial bodies. It is estimated to be approximately 13.8 billion years old and spans an estimated 93 billion [[light-years]] in diameter. The universe is believed to have begun with a massive explosion called the [[Big Bang]], which occurred approximately 13.8 billion years ago. At the time of the Big Bang, the universe was extremely hot and dense, and rapidly expanded and cooled over time. The universe is composed of various types of matter and energy, including [[dark matter]] and [[dark energy]], which are not directly observable but are believed to make up the majority of the universe's mass and energy. Ordinary matter, which includes atoms and molecules, makes up only a small fraction of the universe. The observable universe contains an estimated 2 trillion galaxies, each containing billions of stars. The [[Milky Way]] galaxy, which contains our [[solar system]], is estimated to contain approximately 100 billion stars. The universe also contains various types of celestial bodies, including planets, moons, [[asteroid]], and [[comet]]. The universe is constantly expanding, and the rate of expansion is accelerating. This expansion is believed to be driven by dark energy, which is causing the universe to expand at an increasing rate over time. The study of the universe is a complex and ongoing field of scientific research. Astronomers and cosmologists use various tools and techniques, including telescopes, satellites, and computer simulations, to study the universe and its properties. Through these efforts, scientists have gained a better understanding of the origins, structure, and evolution of the universe, and continue to make new discoveries and advances in our understanding of the cosmos. ==Summary== In summary, the universe is a vast and complex system of galaxies, stars, planets, and other celestial bodies, estimated to be approximately 13.8 billion years old and spanning an estimated 93 billion light-years in diameter. It began with the Big Bang and is constantly expanding, with dark matter and dark energy making up the majority of its mass and energy. Through ongoing scientific research, we continue to gain a better understanding of the universe and its properties. ---- <ref>https://en.m.wikipedia.org/wiki/Universe</ref> __FORCETOC__ __INDEX__ 3e9d8b66b758f9d7679f0ea4243f4b2b1d196a2f Acceleration 0 12 417 22 2023-07-13T17:43:59Z SpaceMan 2 /* Definition */ wikitext text/x-wiki It is defined as the change in the velocity of an object per unit time. If the velocity of an object changes frIt is defined as the change in the om an initial value u to final value v in time t, then acceleration a is given by Acceleration = (final velocity - initial velocity )/ Time ==Properties== SI unit of acceleration is m/s² It is a [[Vector quantity]], its direction is in the direction of change in velocity. It may be positive, negative or zero. If an object is moving with constant or uniform [[velocity]], then its acceleration is zero. ==Uniform acceleration== A body is said to have uniform acceleration, if it travels in a straight line and its velocity increases or decreases by equal [[magnitude]] in equal intervals of time. For example : (ii) The [[motion]] of a bicycle going down the slope of a road (when the rider is not pedaling and [[air resistance]] is negligible). ==Non-Uniform acceleration== A body is said to have non-uniform acceleration, if its velocity changes by unequal magnitude in equal intervals of time. For example - The motion of a car on a crowded road. ==Retardation or deceleration== A body is said to be retarded if the magnitude of its velocity decreases with time. In this case, the final velocity of the moving body is less than the initial velocity i.e., v<u. For example - When a person applies brake on a moving car, its velocity decreases with time. For example, if acceleration is a = - 5 m/s ^ 2 we can write this as the deceleration or retardation is taking place at 5 m/s² or you can also put it as acceleration in the opposite direction at the rate of 5 m/s². 3fbca5aaf469c2008f7d8246b5672bcbe8e9aea8 Active Galactic Nucleus 0 167 418 361 2023-07-13T17:48:00Z SpaceMan 2 /* Definition */ wikitext text/x-wiki An active galactic nucleus (AGN) is a region at the center of a [[galaxy]] that emits a significant amount of [[radiation]] and displays strong variability in its emission properties. This phenomenon is thought to be caused by the accretion of material onto a supermassive [[black hole]] located at the center of the galaxy. As material falls into the black hole, it heats up and emits radiation across the [[electromagnetic spectrum]], from [[radio waves]] to [[gamma-rays]]. This process generates a significant amount of [[energy]], making AGNs some of the most luminous objects in the [[universe]]. AGNs can exhibit a variety of emission features, including broad emission lines, X-ray emission, and strong radio emission. The properties of the emission lines can be used to classify AGNs into different types, such as [[Seyfert galaxies]], [[quasars]], and [[blazars]]. The study of AGNs is an active area of research, with astronomers using a variety of techniques to understand the physical processes that drive their emission. This includes studying the variability of AGNs on various timescales, measuring the properties of the accretion disks and jets that surround the black hole, and investigating the interaction between the black hole and the surrounding gas and stars in the galaxy. AGNs are also important probes of the evolution of galaxies and the growth of supermassive black holes. Understanding the properties and behavior of AGNs is therefore crucial to our understanding of the formation and evolution of the universe as a whole. 802f5aef310eb7884d6ccb05cfca931d3dd0b65b 419 418 2023-07-13T17:51:06Z SpaceMan 2 wikitext text/x-wiki An active galactic nucleus (AGN) is a region at the center of a [[galaxy]] that emits a significant amount of [[radiation]] and displays strong variability in its emission properties. This phenomenon is thought to be caused by the accretion of material onto a supermassive [[black hole]] located at the center of the galaxy. As material falls into the black hole, it heats up and emits radiation across the [[electromagnetic spectrum]], from [[radio waves]] to [[gamma-rays]]. This process generates a significant amount of [[energy]], making AGNs some of the most luminous objects in the [[universe]]. AGNs can exhibit a variety of emission features, including broad emission lines, X-ray emission, and strong radio emission. The properties of the emission lines can be used to classify AGNs into different types, such as [[Seyfert galaxies]], [[quasars]], and [[blazars]]. The study of AGNs is an active area of research, with astronomers using a variety of techniques to understand the physical processes that drive their emission. This includes studying the variability of AGNs on various timescales, measuring the properties of the accretion disks and jets that surround the black hole, and investigating the interaction between the black hole and the surrounding gas and stars in the galaxy. AGNs are also important probes of the evolution of galaxies and the growth of supermassive black holes. Understanding the properties and behavior of AGNs is therefore crucial to our understanding of the formation and evolution of the universe as a whole. ==Technique used to study AGN== Astronomers use a variety of techniques to study active galactic nuclei (AGNs). Here are some of the techniques: 1. Spectroscopy: [[Astronomers]] use spectroscopy to study the emission lines in AGNs. Spectroscopy involves breaking down the light emitted by an AGN into its component wavelengths, revealing information about the elements and physical conditions in the emitting gas. This technique can be used to study the velocity of gas in the accretion disk and measure the mass of the central [[black hole]]. 2. X-ray and Gamma-ray Astronomy: AGNs emit copious amounts of X-rays and gamma rays, which can be detected by [[telescopes]] that are sensitive to these high-energy wavelengths. These observations can provide information about the geometry and physical processes that occur in the [[accretion disk]] and jets around the [[black hole]]. 3. Radio Astronomy: AGNs also emit strong [[radio waves]], which can be detected by radio telescopes. These observations can reveal the structure and properties of the jets that are launched from the AGN, as well as the magnetic fields and other physical conditions in the surrounding gas. 4. Time-domain Astronomy: Astronomers study the variability of AGNs on various timescales, from hours to years. This can provide information about the physical processes that occur near the black hole, such as changes in the accretion rate or the launching of a new jet. 5. Multi-wavelength Astronomy: AGNs emit radiation across the [[electromagnetic spectrum]], from radio waves to [[gamma rays]]. Studying AGNs at multiple wavelengths can provide a more complete picture of their properties and behavior. 414eae25f59d634022fc174b7115fd9d85635d87 421 419 2023-07-13T18:03:50Z SpaceMan 2 wikitext text/x-wiki An active galactic nucleus (AGN) is a region at the center of a [[galaxy]] that emits a significant amount of [[radiation]] and displays strong variability in its emission properties. This phenomenon is thought to be caused by the accretion of material onto a supermassive [[black hole]] located at the center of the galaxy. [[File:Active Galactic nucleus .jpg|alt=Active Galactic nucleus |center|frameless|Credit: C.M. Urry & P. Padovani.]] As material falls into the black hole, it heats up and emits radiation across the [[electromagnetic spectrum]], from [[radio waves]] to [[gamma-rays]]. This process generates a significant amount of [[energy]], making AGNs some of the most luminous objects in the [[universe]]. AGNs can exhibit a variety of emission features, including broad emission lines, X-ray emission, and strong radio emission. The properties of the emission lines can be used to classify AGNs into different types, such as [[Seyfert galaxies]], [[quasars]], and [[blazars]]. The study of AGNs is an active area of research, with astronomers using a variety of techniques to understand the physical processes that drive their emission. This includes studying the variability of AGNs on various timescales, measuring the properties of the accretion disks and jets that surround the black hole, and investigating the interaction between the black hole and the surrounding gas and stars in the galaxy. AGNs are also important probes of the evolution of galaxies and the growth of supermassive black holes. Understanding the properties and behavior of AGNs is therefore crucial to our understanding of the formation and evolution of the universe as a whole. ==Technique used to study AGN== Astronomers use a variety of techniques to study active galactic nuclei (AGNs). Here are some of the techniques: 1. Spectroscopy: [[Astronomers]] use spectroscopy to study the emission lines in AGNs. Spectroscopy involves breaking down the light emitted by an AGN into its component wavelengths, revealing information about the elements and physical conditions in the emitting gas. This technique can be used to study the velocity of gas in the accretion disk and measure the mass of the central [[black hole]]. 2. X-ray and Gamma-ray Astronomy: AGNs emit copious amounts of X-rays and gamma rays, which can be detected by [[telescopes]] that are sensitive to these high-energy wavelengths. These observations can provide information about the geometry and physical processes that occur in the [[accretion disk]] and jets around the [[black hole]]. 3. Radio Astronomy: AGNs also emit strong [[radio waves]], which can be detected by radio telescopes. These observations can reveal the structure and properties of the jets that are launched from the AGN, as well as the magnetic fields and other physical conditions in the surrounding gas. 4. Time-domain Astronomy: Astronomers study the variability of AGNs on various timescales, from hours to years. This can provide information about the physical processes that occur near the black hole, such as changes in the accretion rate or the launching of a new jet. 5. Multi-wavelength Astronomy: AGNs emit radiation across the [[electromagnetic spectrum]], from radio waves to [[gamma rays]]. Studying AGNs at multiple wavelengths can provide a more complete picture of their properties and behavior. 77851a672d20b3298cf9756c2607dfe68b87cadd File:Active Galactic nucleus .jpg 6 188 420 2023-07-13T18:03:14Z SpaceMan 2 wikitext text/x-wiki Credit: C.M. Urry & P. Padovani. 352301842e5e005b54ecf932286dc16abf291772 Dark matter 0 189 422 2023-07-13T18:11:16Z SpaceMan 2 Created page with "Dark matter is a hypothetical form of matter that is thought to make up a significant portion of the total matter content in the [[universe]]. It does not interact with light or other forms of [[electromagnetic radiation]], making it invisible to [[telescopes]] and other instruments that detect light. The existence of dark matter is inferred through its gravitational effects on visible matter, such as [[stars]] and [[galaxies]]. Observations of the velocities of galaxi..." wikitext text/x-wiki Dark matter is a hypothetical form of matter that is thought to make up a significant portion of the total matter content in the [[universe]]. It does not interact with light or other forms of [[electromagnetic radiation]], making it invisible to [[telescopes]] and other instruments that detect light. The existence of dark matter is inferred through its gravitational effects on visible matter, such as [[stars]] and [[galaxies]]. Observations of the velocities of galaxies and galaxy clusters suggest that there is more mass in these systems than can be accounted for by visible matter alone. This discrepancy is attributed to the presence of dark matter. The nature of dark matter is still unknown, but it is believed to be composed of unknown particles that do not interact with light or other forms of electromagnetic radiation. These particles are thought to be electrically neutral and have very little interaction with other matter, making them difficult to detect. Several experiments have been carried out to search for dark matter particles, including experiments that use underground detectors, [[particle accelerators]], and telescopes. However, no direct detection of dark matter has been made so far. Despite its invisible nature, dark matter plays a crucial role in the structure and evolution of the universe. It is thought to have played a key role in the formation of large-scale structures, such as galaxies and [[galaxy clusters]], and its influence can be seen in the [[cosmic microwave background radiation]], the afterglow of the [[Big Bang]]. The study of dark matter is an active area of research in [[astrophysics]] and particle physics, with scientists working to better understand its properties and role in the [[universe]]. ==Additional Details== 1. Dark matter is estimated to make up approximately 85% of the total matter content in the [[universe]]. The remaining 15% is made up of visible matter, such as stars, [[planets]], and gas. 2. Dark matter is believed to be distributed throughout the universe in a "halo" around galaxies and other cosmic structures. It is thought to be most dense in the centers of galaxies and less dense in the outer regions. 3. The properties of dark matter particles are still unknown, but several candidates have been proposed, including [[Weakly Interacting Massive Particles (WIMPs)]], [[Axions]], and [[Sterile Neutrinos]]. 4. The effects of dark matter can be observed through its gravitational lensing of light from distant galaxies and its influence on the rotation curves of galaxies. 5. Dark matter is distinct from [[dark energy]], which is a hypothetical form of energy that is believed to be responsible for the acceleration of the expansion of the universe. Dark energy is thought to make up approximately 70% of the total [[energy]] content of the universe. 6. The study of dark matter is important for understanding the large-scale structure of the universe, the formation and evolution of galaxies, and the fundamental nature of matter and the universe as a whole. Despite decades of research, the nature of dark matter remains one of the biggest mysteries in astrophysics. Scientists continue to search for new ways to detect dark matter particles and better understand their properties and role in the universe. 8cfe537ef0e4dc74e46a51a4f68501353d848f15 424 422 2023-07-13T18:16:34Z SpaceMan 2 wikitext text/x-wiki Dark matter is a hypothetical form of matter that is thought to make up a significant portion of the total matter content in the [[universe]]. It does not interact with light or other forms of [[electromagnetic radiation]], making it invisible to [[telescopes]] and other instruments that detect light. [[File:Dark-matter.jpg|alt=Dark Matter |center|frameless|Image via RAS/ S. Epps & M. Hudson / University of Waterloo.]] The existence of dark matter is inferred through its gravitational effects on visible matter, such as [[stars]] and [[galaxies]]. Observations of the velocities of galaxies and galaxy clusters suggest that there is more mass in these systems than can be accounted for by visible matter alone. This discrepancy is attributed to the presence of dark matter. The nature of dark matter is still unknown, but it is believed to be composed of unknown particles that do not interact with light or other forms of electromagnetic radiation. These particles are thought to be electrically neutral and have very little interaction with other matter, making them difficult to detect. Several experiments have been carried out to search for dark matter particles, including experiments that use underground detectors, [[particle accelerators]], and telescopes. However, no direct detection of dark matter has been made so far. Despite its invisible nature, dark matter plays a crucial role in the structure and evolution of the universe. It is thought to have played a key role in the formation of large-scale structures, such as galaxies and [[galaxy clusters]], and its influence can be seen in the [[cosmic microwave background radiation]], the afterglow of the [[Big Bang]]. The study of dark matter is an active area of research in [[astrophysics]] and particle physics, with scientists working to better understand its properties and role in the [[universe]]. ==Additional Details== 1. Dark matter is estimated to make up approximately 85% of the total matter content in the [[universe]]. The remaining 15% is made up of visible matter, such as stars, [[planets]], and gas. 2. Dark matter is believed to be distributed throughout the universe in a "halo" around galaxies and other cosmic structures. It is thought to be most dense in the centers of galaxies and less dense in the outer regions. 3. The properties of dark matter particles are still unknown, but several candidates have been proposed, including [[Weakly Interacting Massive Particles (WIMPs)]], [[Axions]], and [[Sterile Neutrinos]]. 4. The effects of dark matter can be observed through its gravitational lensing of light from distant galaxies and its influence on the rotation curves of galaxies. 5. Dark matter is distinct from [[dark energy]], which is a hypothetical form of energy that is believed to be responsible for the acceleration of the expansion of the universe. Dark energy is thought to make up approximately 70% of the total [[energy]] content of the universe. 6. The study of dark matter is important for understanding the large-scale structure of the universe, the formation and evolution of galaxies, and the fundamental nature of matter and the universe as a whole. Despite decades of research, the nature of dark matter remains one of the biggest mysteries in astrophysics. Scientists continue to search for new ways to detect dark matter particles and better understand their properties and role in the universe. e488c52821df618778bf1dc0b8cc1a920d0c8553 File:Dark-matter.jpg 6 190 423 2023-07-13T18:16:10Z SpaceMan 2 wikitext text/x-wiki Image via RAS/ S. Epps & M. Hudson / University of Waterloo. 279cd8fe2cde6432ad14fa6c3b685d6d7be78d8e File:Planet .jpg 6 191 426 2023-07-14T04:12:22Z SpaceMan 2 wikitext text/x-wiki Credit: Wikipedia e39e8e58ba05fc1af6dc2fb10cfb0de8592d098b Planet 0 192 427 2023-07-14T04:13:43Z SpaceMan 2 Created page with "A planet is a celestial body that orbits a [[star]] and is massive enough to form a nearly spherical shape under its own [[gravity]]. Planets are one of the most common types of objects in the [[universe]] and are typically composed of rock, metal, or gas. File:Planet .jpg|alt=Planets|center|frameless|The eight planets of the Solar System with size to scale (up to down, left to right): Saturn, Jupiter, Uranus, Neptune (outer planets), Earth, Venus, Mars, and Mercury (i..." wikitext text/x-wiki A planet is a celestial body that orbits a [[star]] and is massive enough to form a nearly spherical shape under its own [[gravity]]. Planets are one of the most common types of objects in the [[universe]] and are typically composed of rock, metal, or gas. [[File:Planet .jpg|alt=Planets|center|frameless|The eight planets of the Solar System with size to scale (up to down, left to right): Saturn, Jupiter, Uranus, Neptune (outer planets), Earth, Venus, Mars, and Mercury (inner planets). Credit: Wikipedia ]] The study of planets is an active area of research in [[astronomy]] and planetary science, with scientists using a variety of techniques to study their properties and behavior. Here are some key features of planets: 1. Formation: Planets are thought to form from the protoplanetary disk of gas and dust that surrounds a young star. Over time, the material in the disk clumps together under the influence of gravity, eventually forming larger and larger objects that eventually become planets. 2. Composition: The composition of planets can vary depending on their distance from their parent star and the conditions in the protoplanetary disk. Terrestrial planets, such as [[Earth]] and [[Mars]], are primarily composed of rock and metal, while gas giants, such as [[Jupiter]] and [[Saturn]], are composed mostly of hydrogen and helium. 3. Atmospheres: Many planets have atmospheres, which are layers of gases that surround the planet. The composition and thickness of the atmosphere can vary depending on the planet's distance from its star and its size. Some planets, such as Earth, have atmospheres that are thick enough to support [[life]]. 4. Moons: Many planets have one or more moons, which are [[natural satellites]] that orbit the planet. Moons can have a significant influence on the behavior of the planet, such as causing tides or affecting the planet's rotation. 5. Orbits: Planets orbit their parent star in elliptical orbits, with the period of the orbit depending on the distance from the star and the planet's mass. The study of planetary orbits is important for understanding the dynamics of the solar system and the formation of planets. The study of planets is crucial for understanding the formation and evolution of the [[solar system]] and the potential for life beyond Earth. By studying planets in our own solar system and around other stars, [[astronomers]] and planetary scientists are able to gain a better understanding of the conditions necessary for the emergence and sustenance of life in the [[universe]]. [[Category:Astronomy]] __FORCETOC__ __INDEX__ __NEWSECTIONLINK__ 7efba2ae5c9f2a72ce630d73f43d8c9410533be3 Planets 0 193 428 2023-07-14T04:19:12Z SpaceMan 2 Redirected page to [[Planet]] wikitext text/x-wiki #REDIRECT [[Planet]] __INDEX__ 48ac313454b965b6eacfdcec5f0c4706b846ff9e